一目見ただけで...
必要なのは、集計関数GROUP BY
を含む句だけです。MAX
SELECT id, MAX(rev)
FROM YourTable
GROUP BY id
それほど単純ではありませんよね?
content
列も必要であることに気付きました。
これは SQL で非常によくある質問です。あるグループ識別子ごとに列に最大値がある行のデータ全体を見つけます。キャリアの中でよく耳にしました。実は、現職の技術面接で答えた質問の一つでした。
実際、スタック オーバーフロー コミュニティがそのような質問に対処するためだけに、「Greatest-n-per-group 」という 1 つのタグを作成したことは非常に一般的です。
基本的に、この問題を解決するには 2 つの方法があります。
単純なサブクエリで結合group-identifier, max-value-in-group
する
このアプローチでは、最初にサブクエリでgroup-identifier, max-value-in-group
(上記で解決済み) を見つけます。group-identifier
次に、テーブルを と の両方で等しいサブクエリに結合しますmax-value-in-group
。
SELECT a.id, a.rev, a.contents
FROM YourTable a
INNER JOIN (
SELECT id, MAX(rev) rev
FROM YourTable
GROUP BY id
) b ON a.id = b.id AND a.rev = b.rev
自分自身との左結合、結合条件とフィルターの微調整
このアプローチでは、テーブルをそれ自体で結合したままにします。平等は に入るgroup-identifier
。次に、2 つのスマートな動き:
- 2 番目の結合条件は、左側の値が右側の値よりも小さいことです
- ステップ 1 を実行すると、実際に最大値を持つ行が
NULL
右側に表示されます (LEFT JOIN
覚えていますか?)。次に、結合された結果をフィルター処理して、右側が である行のみを表示しますNULL
。
したがって、次のようになります。
SELECT a.*
FROM YourTable a
LEFT OUTER JOIN YourTable b
ON a.id = b.id AND a.rev < b.rev
WHERE b.id IS NULL;
結論
どちらのアプローチでも、まったく同じ結果が得られます。
max-value-in-group
forで2 つの行がある場合group-identifier
、両方の行が両方のアプローチの結果になります。
どちらのアプローチも SQL ANSI と互換性があるため、その「フレーバー」に関係なく、お気に入りの RDBMS で動作します。
どちらのアプローチもパフォーマンスに適していますが、マイレージは異なる場合があります (RDBMS、DB 構造、インデックスなど)。したがって、一方のアプローチをもう一方のアプローチよりも優先する場合は、benchmark . そして、あなたにとって最も意味のあるものを選ぶようにしてください.