Her er fem muligheder for at bruge SQL til kun at returnere de rækker, der har den maksimale værdi i deres gruppe.
Disse eksempler fungerer i de fleste større RDBMS'er, inklusive MySQL, MariaDB, Oracle, PostgreSQL, SQLite og SQL Server.
Eksempeldata
Antag, at vi har en tabel med følgende data:
SELECT * FROM Gameshow;
Resultat:
+--------------+--------+---------+ | 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 | +--------------+--------+---------+
Og antag, at vi ønsker at få den højeste score for hver deltager.
Valgmulighed 1
En hurtig og nem mulighed er at konstruere en forespørgsel med SQL GROUP BY
klausul:
SELECT
Contestant,
MAX( Score ) AS MaxScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;
Resultat:
+--------------+------------+ | Contestant | MaxScore | |--------------+------------| | Faye | 85 | | Jet | 51 | | Spike | 27 | +--------------+------------+
Valgmulighed 2
Hvis vi vil inkludere det spil, som hver deltager spillede for at få den maksimale score, så er en måde at gøre det på at bruge en korreleret underforespørgsel som denne:
SELECT
Contestant,
Game,
Score
FROM Gameshow g1
WHERE Score = ( SELECT MAX( g2.Score )
FROM Gameshow g2
WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;
Resultat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Korrelerede underforespørgsler henviser til en eller flere kolonner uden for underforespørgslen. Korrelerede underforespørgsler kan være ineffektive, hovedsageligt på grund af det faktum, at underforespørgslen udføres gentagne gange, én gang for hver række, der kan vælges af den ydre forespørgsel. Korrelerede underforespørgsler er også kendt som gentagne underforespørgsler.
Valgmulighed 3
Vi kan alternativt bruge en ukorreleret underforespørgsel som denne:
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;
Resultat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Ikke-korrelerede underforespørgsler afhænger ikke af den ydre forespørgsel for deres udførelse. De kan udføres fuldstændig uafhængigt af den ydre forespørgsel.
I Oracle skal vi fjerne AS
når du angiver kolonnealiasserne:
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;
Valgmulighed 4
En anden mulighed er at bruge en LEFT JOIN
, sådan her:
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;
Resultat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Valgmulighed 5
En anden måde at hente rækker med den maksimale værdi i en given kolonne på er at bruge et fælles tabeludtryk med vinduesfunktion:
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;
Resultat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+