SQLを使用して、グループ内で最大値を持つ行のみを返すための5つのオプションを次に示します。
これらの例は、MySQL、MariaDB、Oracle、PostgreSQL、SQLite、SQLServerなどのほとんどの主要なRDBMSで機能します。
次のデータを含むテーブルがあるとします。
SELECT * FROM Gameshow;
結果:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Faye | 2 | 50 | | Faye | 3 | 63 | | Jet | 1 | 31 | | Jet | 2 | 40 | | Jet | 3 | 51 | | Spike | 1 | 25 | | Spike | 2 | 27 | | Spike | 3 | 15 | +--------------+--------+---------+
そして、各出場者の最高スコアを取得したいとします。
すばやく簡単なオプションは、SQL GROUP BY
を使用してクエリを作成することです。 条項:
SELECT
Contestant,
MAX( Score ) AS MaxScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;
結果:
+--------------+------------+ | Contestant | MaxScore | |--------------+------------| | Faye | 85 | | Jet | 51 | | Spike | 27 | +--------------+------------+
各競技者が最大スコアを取得するためにプレイしたゲームを含める場合、そのための1つの方法は、次のような相関サブクエリを使用することです。
SELECT
Contestant,
Game,
Score
FROM Gameshow g1
WHERE Score = ( SELECT MAX( g2.Score )
FROM Gameshow g2
WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;
結果:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
相関サブクエリは、サブクエリの外部からの1つ以上の列を参照します。相関サブクエリは、主に、外部クエリによって選択される可能性のある行ごとに1回ずつサブクエリが繰り返し実行されるため、非効率になる可能性があります。相関サブクエリは、繰り返しサブクエリとも呼ばれます。
あるいは、次のような無相関のサブクエリを使用することもできます:
SELECT
g1.Contestant,
g1.Game,
g1.Score
FROM Gameshow g1
JOIN (
SELECT Contestant, MAX( Score ) AS Score
FROM Gameshow
GROUP BY Contestant ) AS g2
ON g1.Contestant = g2.Contestant AND g1.Score = g2.Score
ORDER BY Contestant ASC;
結果:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
相関のないサブクエリは、実行のために外部クエリに依存しません。外部クエリとは完全に独立して実行できます。
Oracleでは、AS
を削除する必要があります 列エイリアスを宣言する場合:
SELECT
g1.Contestant,
g1.Game,
g1.Score
FROM Gameshow g1
JOIN (
SELECT Contestant, MAX( Score ) Score
FROM Gameshow
GROUP BY Contestant ) g2
ON g1.Contestant = g2.Contestant AND g1.Score = g2.Score
ORDER BY Contestant ASC;
もう1つのオプションは、LEFT JOIN
を使用することです。 、このように:
SELECT
g1.Contestant,
g1.Game,
g1.Score
FROM Gameshow g1
LEFT JOIN Gameshow g2 ON
g1.Contestant = g2.Contestant AND g1.Score < g2.Score
WHERE g2.Contestant IS NULL
ORDER BY g1.Contestant ASC;
結果:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
特定の列で最大値を持つ行をフェッチする別の方法は、ウィンドウ関数で一般的なテーブル式を使用することです。
WITH cte AS (
SELECT Contestant, Game, Score,
RANK() OVER ( PARTITION BY Contestant
ORDER BY Score DESC
) AS r
FROM Gameshow
)
SELECT Contestant, Game, Score
FROM cte
WHERE r = 1
ORDER BY Contestant ASC;
結果:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+