sql >> Database teknologi >  >> NoSQL >> MongoDB

5 måder at vælge rækker med den maksimale værdi for deres gruppe i SQL

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

  1. Kan ikke starte/starte lokal mongo db

  2. Migrering af socket.io fra 0.9.x til 1.x, problemer med at konfigurere RedisStore

  3. MongoDB:upsert underdokument

  4. Hvordan fortæller du Mongo om at sortere en samling, før du begrænser resultaterne?