別の列の異なる値ごとに、列の最大値を持つ行を取得します。質問する

別の列の異なる値ごとに、列の最大値を持つ行を取得します。質問する

テーブル:

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 datet2datet1dateuseridt2datet1t1dateuserid

このような場合 (一致がない場合)、 の列t2は になりますNULL(結合条件で指定された列であっても)。 を使用するのはそのためです。これは、指定された に対してWHERE t2.UserId IS NULLより大きい を持つ行が見つからなかったケースを検索するためです。dateuserid

おすすめ記事