多くの人がサブクエリやウィンドウ関数を使用してこれを行っているのを目にしますが、私は次のようにサブクエリなしでこの種のクエリを実行することがよくあります。プレーンな標準SQLを使用しているため、どのブランドのRDBMSでも機能するはずです。
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
言い換えると、 t1
から行をフェッチします 同じUserId
を持つ他の行が存在しない場合 そしてより大きな日付。
(識別子「日付」はSQLの予約語なので、区切り文字で囲みます。)
t1。"Date"=t2。"Date"
の場合 、ダブリングが表示されます。通常、テーブルには auto_inc(seq)
があります キー、例: id
。ダブリングを回避するには、次のように使用できます。
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date")
OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;
@Farhanからのコメントを再確認してください:
詳細な説明は次のとおりです:
外部結合はt1
に結合しようとします t2
を使用 。デフォルトでは、 t1
のすべての結果 が返され、 if t2
に一致があります 、それも返されます。 t2
に一致するものがない場合 t1
の特定の行に対して 、その後、クエリは引き続き t1
の行を返します 、 NULL
を使用します すべてのt2
のプレースホルダーとして の列。これが、外部結合が一般的に機能する方法です。
このクエリの秘訣は、 t2
となるように結合の一致条件を設計することです。 同じと一致する必要があります userid
、およびより大きい 日付コード> 。
t2
に行が存在するかどうかという考え方 date
が大きい 、次に t1
の行 できないと比較されます 最高のdate
そのuserid
。ただし、一致するものがない場合、つまり t2
に行が存在しない場合 date
が大きい t1
の行より -- t1
の行が date
が最大の行でした 指定されたuserid
に対して 。
そのような場合(一致するものがない場合)、 t2
の列 NULL
になります -結合条件で指定された列ですら。そのため、 WHERE t2.UserId IS NULL
を使用します 、 date
より大きい行が見つからなかったケースを検索しているため 指定されたuserid
に対して 。