1. ホーム
  2. mysql

[解決済み] SQLでカラムに最大値を持つ行のみを選択する [重複]。

2022-03-20 23:32:42

質問

ドキュメント用にこんな表があります(簡易版はこちら)。

<テーブル イド レヴ コンテンツ 1 1 ... 2 1 ... 1 2 ... 1 3 ...

idごとに1行、最大revだけを選択するには?
上記のデータでは、結果には2つの行が含まれるはずです。 [1, 3, ...][2, 1, ..] . 私は MySQL .

現在、私はチェックを while ループで、結果セットから古いレヴを検出して上書きしています。しかし、これは結果を得るための唯一の方法なのでしょうか?また SQL の解決策になりますか?

どのように解決するのですか?

一見すると...

必要なのは GROUP BY 節に MAX のアグリゲート関数を使用します。

SELECT id, MAX(rev)
FROM YourTable
GROUP BY id

そんな単純な話じゃないだろう?

今気づいたのですが content カラムもあります。

これはSQLで非常によくある質問です。あるグループ識別子ごとに、ある列の最大値を持つ行のデータ全体を見つけることです。私はキャリアの中でこれをよく耳にしました。実際、今の仕事の技術面接で答えた質問の一つでもあります。

このような質問はよくあることなので、Stack Overflowコミュニティでは、このような質問に対応するためのタグを作成したほどです。 最大のNパーグループ .

基本的に、その問題を解決するために2つのアプローチがあります。

シンプルな結合 group-identifier, max-value-in-group サブクエリ

この方法では、まず group-identifier, max-value-in-group (上記で解決済み) をサブクエリで作成します。次に、テーブルをサブクエリに結合します。 group-identifiermax-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つのスマートな動き。

  1. 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;

まとめ

どちらのアプローチも全く同じ結果をもたらします。

を持つ2つの行がある場合 max-value-in-group に対して group-identifier の場合、どちらの方法でも、両方の行が結果に含まれることになります。

どちらのアプローチもSQL ANSI互換なので、お使いのRDBMSの種類に関係なく動作します。

また、どちらのアプローチもパフォーマンスに優れていますが、お客様の使用状況(RDBMS、DB構造、インデックスなど)により異なる可能性があります。だから、どちらかのアプローチを選ぶときは ベンチマーク . そして、あなたにとって最も理にかなっているものを選ぶようにしてください。