MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

5 Möglichkeiten, Zeilen mit dem Maximalwert für ihre Gruppe in SQL auszuwählen

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