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 .