Voici cinq options pour utiliser SQL pour renvoyer uniquement les lignes qui ont la valeur maximale dans leur groupe.
Ces exemples fonctionnent dans la plupart des principaux SGBDR, y compris MySQL, MariaDB, Oracle, PostgreSQL, SQLite et SQL Server.
Exemple de données
Supposons que nous ayons un tableau avec les données suivantes :
SELECT * FROM Gameshow;
Résultat :
+--------------+--------+---------+ | 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 | +--------------+--------+---------+
Et supposons que nous voulions obtenir le score le plus élevé pour chaque concurrent.
Option 1
Une option simple et rapide consiste à construire une requête avec le SQL GROUP BY
clause :
SELECT
Contestant,
MAX( Score ) AS MaxScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;
Résultat :
+--------------+------------+ | Contestant | MaxScore | |--------------+------------| | Faye | 85 | | Jet | 51 | | Spike | 27 | +--------------+------------+
Option 2
Si nous voulons inclure le jeu auquel chaque concurrent a joué pour obtenir le score maximum, une façon de le faire est d'utiliser une sous-requête corrélée comme celle-ci :
SELECT
Contestant,
Game,
Score
FROM Gameshow g1
WHERE Score = ( SELECT MAX( g2.Score )
FROM Gameshow g2
WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;
Résultat :
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Les sous-requêtes corrélées font référence à une ou plusieurs colonnes extérieures à la sous-requête. Les sous-requêtes corrélées peuvent être inefficaces, principalement en raison du fait que la sous-requête est exécutée à plusieurs reprises, une fois pour chaque ligne susceptible d'être sélectionnée par la requête externe. Les sous-requêtes corrélées sont également appelées sous-requêtes répétitives.
Option 3
Nous pouvons également utiliser une sous-requête non corrélée comme celle-ci :
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;
Résultat :
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Les sous-requêtes non corrélées ne dépendent pas de la requête externe pour leur exécution. Ils peuvent s'exécuter complètement indépendamment de la requête externe.
Dans Oracle, nous devons supprimer le AS
lors de la déclaration des alias de colonnes :
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
Une autre option consiste à utiliser un LEFT JOIN
, comme ceci :
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;
Résultat :
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+
Option 5
Une autre façon de récupérer les lignes avec la valeur maximale dans une colonne donnée consiste à utiliser une expression de table commune avec la fonction de fenêtre :
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;
Résultat :
+--------------+--------+---------+ | Contestant | Game | Score | |--------------+--------+---------| | Faye | 1 | 85 | | Jet | 3 | 51 | | Spike | 2 | 27 | +--------------+--------+---------+