Hier zijn vijf opties om SQL te gebruiken om alleen die rijen te retourneren die de minimale waarde binnen hun groep hebben.
Deze voorbeelden werken in de meeste grote RDBMS'en, waaronder MySQL, MariaDB, Oracle, PostgreSQL, SQLite en SQL Server.
Voorbeeldgegevens
Stel dat we een tabel hebben met de volgende gegevens:
SELECT * FROM Gameshow;
Resultaat:
+--------------+--------+---------+ | 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 | +--------------+--------+---------+
En stel dat we voor elke deelnemer de laagste score willen halen.
Optie 1
Een snelle en gemakkelijke optie is om een query te maken met de SQL GROUP BY
clausule:
SELECT
Contestant,
MIN( Score ) AS MinScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;
Resultaat:
+--------------+------------+ | Contestant | MinScore | |--------------+------------| | Faye | 50 | | Jet | 31 | | Spike | 15 | +--------------+------------+
Optie 2
Als we het spel willen opnemen dat elke deelnemer heeft gespeeld om de minimumscore te behalen, dan is een manier om dat te doen het gebruik van een gecorreleerde subquery zoals deze:
SELECT
Contestant,
Game,
Score
FROM Gameshow g1
WHERE Score = ( SELECT MIN( g2.Score )
FROM Gameshow g2
WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;
Resultaat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 2 | 50 | | Jet | 1 | 31 | | Spike | 3 | 15 | +--------------+--------+---------+
Gecorreleerde subquery's verwijzen naar een of meer kolommen van buiten de subquery. Gecorreleerde subquery's kunnen inefficiënt zijn, voornamelijk vanwege het feit dat de subquery herhaaldelijk wordt uitgevoerd, één keer voor elke rij die door de buitenste query kan worden geselecteerd. Gecorreleerde subquery's worden ook wel herhalende subquery's genoemd.
Optie 3
We kunnen ook een niet-gecorreleerde subquery als deze gebruiken:
SELECT
g1.Contestant,
g1.Game,
g1.Score
FROM Gameshow g1
JOIN (
SELECT Contestant, MIN( Score ) AS Score
FROM Gameshow
GROUP BY Contestant ) AS g2
ON g1.Contestant = g2.Contestant AND g1.Score = g2.Score
ORDER BY Contestant ASC;
Resultaat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 2 | 50 | | Jet | 1 | 31 | | Spike | 3 | 15 | +--------------+--------+---------+
Niet-gecorreleerde subquery's zijn niet afhankelijk van de buitenste query voor hun uitvoering. Ze kunnen volledig onafhankelijk van de buitenste query worden uitgevoerd.
In Oracle moeten we de AS
. verwijderen bij het declareren van de kolomaliassen:
SELECT
g1.Contestant,
g1.Game,
g1.Score
FROM Gameshow g1
JOIN (
SELECT Contestant, MIN( Score ) Score
FROM Gameshow
GROUP BY Contestant ) g2
ON g1.Contestant = g2.Contestant AND g1.Score = g2.Score
ORDER BY Contestant ASC;
Optie 4
Een andere manier om rijen met de minimumwaarde in een bepaalde kolom op te halen, is door een LEFT JOIN
te gebruiken. , zoals dit:
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;
Resultaat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 2 | 50 | | Jet | 1 | 31 | | Spike | 3 | 15 | +--------------+--------+---------+
Optie 5
Een andere manier om dit te doen is door een algemene tabeluitdrukking met vensterfunctie te gebruiken:
WITH cte AS (
SELECT Contestant, Game, Score,
RANK() OVER ( PARTITION BY Contestant
ORDER BY Score ASC
) AS r
FROM Gameshow
)
SELECT Contestant, Game, Score
FROM cte
WHERE r = 1
ORDER BY Contestant ASC;
Resultaat:
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 2 | 50 | | Jet | 1 | 31 | | Spike | 3 | 15 | +--------------+--------+---------+