sql >> Databáze >  >> NoSQL >> MongoDB

5 způsobů, jak vybrat řádky s maximální hodnotou pro jejich skupinu v SQL

Zde je pět možností, jak pomocí SQL vrátit pouze ty řádky, které mají v rámci své skupiny maximální hodnotu.

Tyto příklady fungují ve většině hlavních RDBMS, včetně MySQL, MariaDB, Oracle, PostgreSQL, SQLite a SQL Server.

Ukázková data

Předpokládejme, že máme tabulku s následujícími údaji:

SELECT * FROM Gameshow;

Výsledek:

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

A předpokládejme, že chceme získat nejvyšší skóre pro každého soutěžícího.

Možnost 1

Rychlou a snadnou možností je vytvořit dotaz pomocí SQL GROUP BY klauzule:

SELECT 
    Contestant,
    MAX( Score ) AS MaxScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;

Výsledek:

+--------------+------------+
| Contestant   | MaxScore   |
|--------------+------------|
| Faye         | 85         |
| Jet          | 51         |
| Spike        | 27         |
+--------------+------------+

Možnost 2

Pokud chceme zahrnout hru, kterou každý soutěžící hrál, aby získal maximální skóre, pak jedním ze způsobů, jak toho dosáhnout, je použít korelovaný dílčí dotaz, jako je tento:

SELECT 
    Contestant,
    Game,
    Score
FROM Gameshow g1
WHERE Score = ( SELECT MAX( g2.Score )
              FROM Gameshow g2
              WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;

Výsledek:

+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

Korelované poddotazy odkazují na jeden nebo více sloupců mimo poddotaz. Korelované poddotazy mohou být neefektivní, hlavně kvůli skutečnosti, že poddotaz se provádí opakovaně, jednou pro každý řádek, který může být vybrán vnějším dotazem. Korelované poddotazy jsou také známé jako opakující se poddotazy.

Možnost 3

Alternativně můžeme použít nekorelovaný poddotaz takto:

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;

Výsledek:

+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

Nekorelované poddotazy nezávisí na vnějším dotazu pro jejich provedení. Mohou se provádět zcela nezávisle na vnějším dotazu.

V Oracle musíme odstranit AS při deklaraci aliasů sloupců:

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;

Možnost 4

Další možností je použít LEFT JOIN , takto:

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;

Výsledek:

+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

Možnost 5

Dalším způsobem, jak načíst řádky s maximální hodnotou v daném sloupci, je použít běžný tabulkový výraz s funkcí okna:

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;

Výsledek:

+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

  1. Mongoose přepíše dokument spíše než pole `$set`

  2. Mongodb se nespustí

  3. Implementace stránkování v mongodb

  4. Chyba pole v objektu 'cíl' na poli '':zamítnutá hodnota []; kódy [typeMismatch.target.,typeMismatch.,typeMismatch.java.util.Date,typeMismatch]