0

イベント テーブル:

id  user    type    creation_date   update_date

1   A       AAA     1111            3333
2   A       BBB     2222            4444
3   A       CCC     3333            5555
4   A       DDD     4444            6666
5   B       AAA     3333            4444
6   B       BBB     4444            5555
7   B       CCC     5555            6666
8   C       AAA     2222            3333
9   C       BBB     1111            7777
10  C       CCC     3333            4444
11  C       DDD     4444            9999

タスク:

少なくとも 1 つの DDD イベントがあり、作成日までのユーザーの最新の非 DDD イベントが update_date までの最新の非 DDD イベントと異なるすべてのユーザーを検索します。

したがって、上記のレコードの場合:

ユーザー A には DDD イベントがあります。良い。ただし、最後に作成された非 DDD イベントと最後に更新された非 DDD イベントは同じです (イベント #3)。したがって、結果セットから除外されます。

ユーザー B には DDD イベントはありません。したがって、結果セットから除外されます。

ユーザー C には DDD イベントがあります。また、最後に作成された非 DDD イベント (#10) は、最後に更新された非 DDD イベント (#9) とは異なります。したがって、結果セットに含まれます。

結果セット:

user
C

GROUP BY や EXISTS など、さまざまなことを試しました。しかし、レコードの各グループを並べ替えるのに苦労しています。

何か案が?

4

2 に答える 2

2

これはさらに良いアイデアです:

SELECT e.usr
FROM  (SELECT usr FROM event WHERE type = 'DDD') u
JOIN   event e USING (usr)
WHERE  e.type <> 'DDD'
GROUP  BY e.usr
HAVING NOT EXISTS (
   SELECT 1 FROM event e0
   WHERE e0.creation_date = max(e.creation_date) 
   AND   e0.update_date   = max(e.update_date)
   AND   e0.usr = e.usr
   AND   e0.type <> 'DDD'
   )
ORDER  BY 1;

それは今と同じくらい簡単で速いはずです。適切なインデックスがあれば、これは飛ぶはずです。

後者は標準 SQL の予約語であるため、usr代わりにを使用します。user

  • サブクエリuで、少なくとも 1 つの行を持つすべてのユーザーを取得しますtype = 'DDD'

  • このセットをベース テーブルに結合し、異なるイベントを持つ同じユーザーのすべての行を取得します ( type <> 'DDD)。

  • 句では、 latestとHAVINGlatest の行がある場合を除外します。creation_dateupdate_date

  • このクエリは、ベース テーブル内の重複に対しても機能します。

最初の試み

遅くて賢くない:

SELECT e.usr
FROM  (SELECT usr FROM event WHERE type = 'DDD') u
JOIN   event e USING (usr)
WHERE  e.type <> 'DDD'
GROUP  BY e.usr
HAVING (SELECT id FROM event WHERE creation_date = max(e.creation_date) AND usr = e.usr AND type <> 'DDD')
    <> (SELECT id FROM event WHERE update_date   = max(e.update_date  ) AND usr = e.usr AND type <> 'DDD')
ORDER  BY 1
  • このクエリは、同じユーザーに対して同時に複数のイベントが発生しないことを前提としています。そうでなければ、それは信頼できません。

->両方を表示するSQLfiddle

于 2013-03-22T22:16:30.990 に答える
1

これを少し単純化できるかどうかはまだ疑問ですが、これを使用できます。

SELECT DISTINCT user
FROM   yourtable
WHERE  user NOT IN (
  SELECT user
  FROM   yourtable t1
  WHERE
    EXISTS (
      SELECT   NULL
      FROM     yourtable t2
      WHERE    t2.type!='DDD' AND t1.user=t2.user
      GROUP BY user
      HAVING   max(t2.creation_date)=t1.creation_date
             AND max(t2.update_date)=t1.update_date)
  )
  AND EXISTS (SELECT null
              FROM yourtable t2
              WHERE t2.user=yourtable.user
                    AND type='DDD')

ここでフィドルを参照してください。

于 2013-03-22T22:38:56.477 に答える