MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

5 façons de sélectionner des lignes avec la valeur maximale pour leur groupe en SQL

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      |
+--------------+--------+---------+