テーブル:
UserId, Value, Date.
各 UserId の最大値 (日付) の UserId 値を取得したいです。つまり、最新の日付を持つ各 UserId の値です。
これを SQL で実行するにはどうすればよいですか? (できれば Oracle を使用してください。)
すべての UserId を取得する必要があります。ただし、各 UserId については、そのユーザーの最新の日付がある行のみを取得する必要があります。
ベストアンサー1
多くの人がサブクエリやウィンドウ関数を使用してこれを実行しているのを目にしますが、私は次のようにサブクエリを使用せずにこの種のクエリを実行することがよくあります。これはプレーンな標準 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
日付またはそれより大きい日付を持つ他の行が存在しない行を取得します。
(識別子「Date」は 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
が返され、に一致するものがあればそれt2
も返されます。t2
の特定の行に に一致するものがない場合でもt1
、クエリは の行を返しt1
、のNULL
すべての列のプレースホルダーとしてを使用しますt2
。これが外部結合の一般的な動作です。
このクエリの秘訣は、結合の一致条件を設計して、 が同じ かつより大きいにt2
一致する必要があるようにすることです。 つまり、 に より大きい を持つ行が存在する場合、それと比較されるの行はその に対して最大になることはできないということです。 しかし、一致しない場合、つまりの行よりもが大きい を持つ の行が に存在しない場合は、 の行が、指定された に対して最大である行であることがわかります。 userid
date
t2
date
t1
date
userid
t2
date
t1
t1
date
userid
このような場合 (一致がない場合)、 の列t2
は になりますNULL
(結合条件で指定された列であっても)。 を使用するのはそのためです。これは、指定された に対してWHERE t2.UserId IS NULL
より大きい を持つ行が見つからなかったケースを検索するためです。date
userid