Hier sind fünf Optionen für die Verwendung von SQL, um nur die Zeilen zurückzugeben, die den maximalen Wert in ihrer Gruppe haben.
Diese Beispiele funktionieren in den meisten wichtigen RDBMSs, einschließlich MySQL, MariaDB, Oracle, PostgreSQL, SQLite und SQL Server.
Beispieldaten
Angenommen, wir haben eine Tabelle mit den folgenden Daten:
SELECT * FROM Gameshow;
Ergebnis:
+--------------+--------+---------+ | 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 | +--------------+--------+---------+
Und angenommen, wir wollen für jeden Teilnehmer die höchste Punktzahl erzielen.
Option 1
Eine schnelle und einfache Möglichkeit besteht darin, eine Abfrage mit dem SQL GROUP BY
zu erstellen Klausel:
SELECT
Contestant,
MAX( Score ) AS MaxScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;
Ergebnis:
+--------------+------------+ | Contestant | MaxScore | |--------------+------------| | Faye | 85 | | Jet | 51 | | Spike | 27 | +--------------+------------+
Option 2
Wenn wir das Spiel einbeziehen möchten, das jeder Teilnehmer gespielt hat, um die maximale Punktzahl zu erreichen, dann besteht eine Möglichkeit darin, eine korrelierte Unterabfrage wie diese zu verwenden:
SELECT
Contestant,
Game,
Score
FROM Gameshow g1
WHERE Score = ( SELECT MAX( g2.Score )
FROM Gameshow g2
WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;
Ergebnis:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Korrelierte Unterabfragen beziehen sich auf eine oder mehrere Spalten außerhalb der Unterabfrage. Korrelierte Unterabfragen können ineffizient sein, hauptsächlich aufgrund der Tatsache, dass die Unterabfrage wiederholt ausgeführt wird, einmal für jede Zeile, die von der äußeren Abfrage ausgewählt werden könnte. Korrelierte Unterabfragen werden auch als sich wiederholende Unterabfragen bezeichnet.
Option 3
Wir können alternativ eine unkorrelierte Unterabfrage wie diese verwenden:
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;
Ergebnis:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Unkorrelierte Unterabfragen sind für ihre Ausführung nicht von der äußeren Abfrage abhängig. Sie können völlig unabhängig von der äußeren Abfrage ausgeführt werden.
In Oracle müssen wir den AS
entfernen beim Deklarieren der Spaltenaliase:
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;
Option 4
Eine weitere Option ist die Verwendung eines LEFT JOIN
, etwa so:
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;
Ergebnis:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Option 5
Eine andere Möglichkeit, Zeilen mit dem Maximalwert in einer bestimmten Spalte abzurufen, besteht darin, einen allgemeinen Tabellenausdruck mit Fensterfunktion zu verwenden:
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;
Ergebnis:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+