sql >> Databáze >  >> RDS >> Database

Jak vybrat první řádek v každé GROUP BY Group

Problém:

Seskupili jste svá data pomocí GROUP BY a chtěli byste zobrazit pouze první řádek z každé skupiny.

Příklad:

Naše databáze obsahuje tabulku s názvem exam_results s údaji v následující tabulce:

first_name last_name rok výsledek
Jan Klein 2020 40
Edith Černá 2020 43
Označit Johnson 2019 32
Laura Léto 2020 35
Kate Smith 2019 41
Jacob Černá 2019 44
Tome Bennett 2020 38
Emily Kelly 2020 43

Pro každý rok najdeme studenta s nejlepším result . Pokud jsou ve skupině dva studenti nerozhodně o nejlepšího, vybereme jednoho z nich k zobrazení.

Řešení:

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 1;

Výsledek je:

first_name last_name rok výsledek row_number
Jacob Černá 2019 44 1
Emily Kelly 2020 43 1

Diskuse:

Nejprve musíte napsat CTE, ve kterém přiřadíte číslo každému řádku v každé skupině. K tomu můžete použít ROW_NUMBER() funkce. V OVER() , určíte skupiny, do kterých mají být řádky rozděleny (PARTITION BY ) a pořadí, ve kterém mají být čísla přiřazena k řádkům (ORDER BY ).

Podívejte se na výsledek vnitřního dotazu:

SELECT
  *,
  ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results;
first_name last_name rok výsledek row_number
Jacob Černá 2019 44 1
Kate Smith 2019 41 2
Označit Johnson 2019 32 3
Emily Kelly 2020 43 1
Edith Černá 2020 43 2
Jan Klein 2020 40 3
Tome Bennett 2020 38 4
Laura Léto 2020 35 5

V rámci každé skupiny (tj. roku) přiřadíte čísla řádků. Každý řádek má číslo řádku podle hodnoty result sloupec. Řádky jsou seřazeny v sestupném pořadí kvůli DESC klíčové slovo po ORDER BY result . I když je ve skupině více řádků, které mají stejnou hodnotu result , řádky mají stále jiná čísla. Zde mají Edith Black a Emily Kelly stejný result ale jiná čísla řádků. Chcete-li toto chování změnit a přiřadit stejné číslo řádku pro stejný výsledek v rámci skupiny, použijte RANK() nebo DENSE_RANK() místo ROW_NUMBER() .

Ve vnějším dotazu vyberete všechna data z CTE (added_row_number ) a použijte WHERE podmínku určující, který řádek z každé skupiny se má zobrazit. Zde chceme zobrazit první řádek, takže podmínka je row_number = 1 .

Všimněte si, že řešení můžete snadno upravit, abyste získali například druhý řádek každé skupiny.

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 2;

Zde je výsledek:

first_name last_name rok výsledek row_number
Kate Smith 2019 41 2
Edith Černá 2020 43 2

Na druhou stranu, pokud chcete získat řádek(y) s druhou nejvyšší hodnotou z result v každé skupině byste měli použít DENSE_RANK() funkce. Zatímco ROW_NUMBER() funkce vytváří po sobě jdoucí čísla pro každý řádek ve skupině, což vede k různým hodnotám přiřazeným k řádkům se stejným výsledkem, DENSE_RANK() funkce dává stejné číslo řádkům se stejným výsledkem.

WITH added_dense_rank AS (
  SELECT
    *,
    DENSE_RANK() OVER(PARTITION BY year ORDER BY result DESC) AS rank
  FROM exam_results
)
SELECT
  *
FROM added_dense_rank
WHERE rank = 2;
first_name last_name rok výsledek hodnocení
Kate Smith 2019 41 2
Jan Klein 2020 40 2

Můžete vidět, že John Klein má druhou nejvyšší hodnotu result (40) pro rok 2020. John Klein je ve skutečnosti třetí osobou ve skupině, ale první dva studenti mají stejný result a oba mají rank = 1 .


  1. Třídění dat v databázi sqlite?

  2. Více příkazů INSERT mysql v jednom dotazu php

  3. Jak funguje operátor LIKE v SQLite

  4. Chyba Ruby/PgSQL při spuštění Rails:nelze načíst takový soubor -- pg_ext (LoadError)