sql >> Databasteknik >  >> NoSQL >> MongoDB

5 sätt att välja rader med det maximala värdet för sin grupp i SQL

Här är fem alternativ för att använda SQL för att endast returnera de rader som har det maximala värdet inom sin grupp.

Dessa exempel fungerar i de flesta större RDBMS, inklusive MySQL, MariaDB, Oracle, PostgreSQL, SQLite och SQL Server.

Exempeldata

Anta att vi har en tabell med följande 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      |
+--------------+--------+---------+

Och anta att vi vill få högsta poäng för varje tävlande.

Alternativ 1

Ett snabbt och enkelt alternativ är att skapa en fråga 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         |
+--------------+------------+

Alternativ 2

Om vi ​​vill inkludera spelet som varje tävlande spelade för att få maxpoäng, så är ett sätt att göra det att använda en korrelerad underfråga så här:

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

Korrelerade underfrågor hänvisar till en eller flera kolumner utanför underfrågan. Korrelerade underfrågor kan vara ineffektiva, främst på grund av att underfrågan exekveras upprepade gånger, en gång för varje rad som kan väljas av den yttre frågan. Korrelerade underfrågor kallas även upprepade underfrågor.

Alternativ 3

Vi kan alternativt använda en okorrelerad underfråga så här:

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

Okorrelerade underfrågor beror inte på den yttre frågan för deras exekvering. De kan köras helt oberoende av den yttre frågan.

I Oracle måste vi ta bort AS när du deklarerar kolumnaliasen:

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;

Alternativ 4

Ett annat alternativ är att använda en LEFT JOIN , så här:

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

Alternativ 5

Ett annat sätt att hämta rader med det maximala värdet i en given kolumn är att använda ett vanligt tabelluttryck med fönsterfunktion:

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. MongoDB $bsonSize

  2. Hur man stoppar ett runaway-indexbygge i MongoDB

  3. Konfigurera singleton-anslutning med node.js och mongo

  4. Itererar över en mongodb-markör i serie (väntar på återuppringningar innan du går till nästa dokument)