0

次のイベントの日付を見つけるソリューションは見つかりましたが、イベントのすべてのデータを含むソリューションは見つかりませんでした。不正行為でそれを成し遂げることができますが、それは mysql でのみ機能し、vertica では失敗します。

これが私が解決しようとしている問題です:

a に続き、タイプ a ではない最初のイベント X からのデータを含むすべてのイベント a を表示したいと考えています。カット アンド ペーストの例を以下に示します。

CREATE TABLE events (user_id int ,created_at int, event varchar(20));
INSERT INTO events values (0,0, 'a');
INSERT INTO events values (0,1, 'b');
INSERT INTO events values (0,2, 'c');
INSERT INTO events values (0,3, 'a');
INSERT INTO events values (0,4, 'c');
INSERT INTO events values (0,5, 'b');
INSERT INTO events values (0,6, 'a');
INSERT INTO events values (0,7, 'a');
INSERT INTO events values (0,8, 'd');

SELECT * FROM events;
+---------+------------+-------+
| user_id | created_at | event |
+---------+------------+-------+
|       0 |          0 | a     |
|       0 |          1 | b     |
|       0 |          2 | c     |
|       0 |          3 | a     |
|       0 |          4 | c     |
|       0 |          5 | b     |
|       0 |          6 | a     |
|       0 |          7 | a     |
|       0 |          8 | d     |
+---------+------------+-------+
9 rows in set (0.00 sec)

両方を取得する方法を知っている結果は次のとおりですが、イベント情報も取得できないようです。

SELECT user_id, MAX(purchased) AS purchased, spent 
FROM ( 
    SELECT
        e1.user_id AS user_id, e1.created_at AS purchased, 
        MIN(e2.created_at) AS spent
    FROM events e1, events e2
    WHERE
        e1.user_id = e2.user_id AND e1.created_at <= e2.created_at AND
        e1.Event = 'a' AND e2.Event != 'a'
    GROUP BY e1.user_id, e1.created_at
) e3 GROUP BY user_id, spent;

 user_id | purchased | spent 
---------+-----------+-------
       0 |         0 |     1
       0 |         3 |     4
       0 |         7 |     8

ここでイベント タイプも必要な場合、上記のクエリでは機能しません。これは、group-by (必要なものではない) または集計 (必要なものではない) でイベント フィールドを使用する必要があるためです。また)。mysqlで十分に面白いですが、私はその不正行為を考えています。これにはverticaを使用する必要があるため、役に立ちません:

SELECT user_id, MAX(purchased) as purchased, spent, event FROM (
    SELECT 
        e1.User_ID AS user_id, 
        e1.created_at AS purchased, 
        MIN(e2.created_at) AS spent, 
        e2.event AS event 
    FROM events e1, events e2 
    WHERE 
        e1.user_id = e2.user_id AND e1.created_at <= e2.created_at AND 
        e1.Event = 'a' AND e2.Event != 'a' 
    GROUP BY
        e1.user_id,e1.created_at
 ) e3 GROUP BY user_id, spent;


+---------+-----------+-------+-------+
| user_id | purchased | spent | event |
+---------+-----------+-------+-------+
|       0 |         0 |     1 | b     |
|       0 |         3 |     4 | c     |
|       0 |         7 |     8 | d     |
+---------+-----------+-------+-------+
3 rows in set (0.00 sec)

vertica の場合、同じクエリで次のエラーがスローされます: ERROR 2640: Column "e2.event" must appear in the GROUP BY clause or be used in an aggregate function

チートを許可しない vertica またはその他のデータベースで実行したときに上記と同じ結果を得ることができるように、2 つのイベントをすべての列とペアにして不正行為を行わずに取得するためのエレガントなソリューションは何ですか? サンプル データでは、必要な追加の列が 1 つだけあります。これはイベント タイプですが、実際には 2 つまたは 3 つの列になります。

回答する前に投稿されたサンプルデータで試してみてください:)

4

3 に答える 3

0

わかりました。あなたが何をしようとしているのかを100%理解できるかどうかはわかりませんが、これが機能しないかどうかを確認してください。

SELECT e3.user_id, MAX(e3.purchased) AS purchased, e3.spent, e.event
FROM ( 
    SELECT
        e1.user_id AS user_id, e1.created_at AS purchased, 
        MIN(e2.created_at) AS spent
    FROM events e1, events e2
    WHERE
        e1.user_id = e2.user_id AND e1.created_at <= e2.created_at AND
        e1.Event = 'a' AND e2.Event != 'a'
    GROUP BY e1.user_id, e1.created_at
) e3 
 JOIN events e on e3.user_id = e.user_id and e3.spent = e.created_at
GROUP BY e3.user_id, e3.spent, e.event

基本的に、私はあなたの主キーであるuser_idと仮定して、イベントテーブルに再び参加しています。created_at

そして、これがSQLFiddleです。

于 2013-01-10T20:38:13.003 に答える
0

これを試して...

With    Cte As
(
        Select  Row_Number() Over (Partition By [user_id] Order By [created_at]) As row_num,
                [user_id],
                [created_at],
                [event]
        From    [events]
)
Select  c1.[user_id],
        c1.[created_at] As purchased,
        c2.[created_at] As spent,
        c2.[event]
From    Cte c1
Left    Join Cte c2
        On  c1.row_num = c2.row_num - 1
Where   c1.event = 'a'
And     c2.event <> 'a'
于 2013-01-10T20:38:14.087 に答える
0

私は通常、相関サブクエリを使用して「次の」計算を行い、元のテーブルに結合します。この場合、 が行を一意に定義すると仮定しています。

クエリは次のとおりです。

SELECT user_id, MAX(purchased) as purchased, spent, event
FROM (
    SELECT e.User_ID, e.created_at AS purchased, 
           MIN(enext.created_at) AS spent,
           min(enext.event) AS event 
    FROM (select e.*,
                 (select MIN(e2.created_at)
                  from event e2
                  where e2.user_id = e.user_id and e2.created_at > e.created_at and e2.event <> 'a'
                 ) nextcreatedat
          from events e
          where e.event = 'a'
         ) e left outer join
         events enext
         on e.user_id = enext.user_id and
            e.nextcreatedat = enext.create_at
    GROUP BY e.user_id, e.created_at
    ) e3
 GROUP BY user_id, spent;

集計GROUP BY e.user_id, e.created_atは必要ありませんが、元のクエリと同じように残しておきます。

Vertica は累積合計をサポートしているため、これをより効率的に行う方法がありますが、MySQL では機能しません。

于 2013-01-10T20:45:55.817 に答える