Problem:
Pogrupowałeś swoje dane za pomocą GROUP BY i chciałby wyświetlić tylko pierwszy wiersz z każdej grupy.
Przykład:
Nasza baza danych zawiera tabelę o nazwie exam_results z danymi w poniższej tabeli:
| imię | nazwisko | rok | wynik |
|---|---|---|---|
| Jan | Klein | 2020 | 40 |
| Edycja | Czarny | 2020 | 43 |
| Zaznacz | Johnson | 2019 | 32 |
| Laura | Lato | 2020 | 35 |
| Kate | Kowalski | 2019 | 41 |
| Jacob | Czarny | 2019 | 44 |
| Tomek | Bennet | 2020 | 38 |
| Emilia | Kelly | 2020 | 43 |
Na każdy rok znajdźmy ucznia z najlepszym result . Jeśli w grupie remisuje dwóch uczniów, arbitralnie wybierzemy jednego do wyświetlenia.
Rozwiązanie:
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;
Wynik:
| imię | nazwisko | rok | wynik | numer wiersza |
|---|---|---|---|---|
| Jacob | Czarny | 2019 | 44 | 1 |
| Emilia | Kelly | 2020 | 43 | 1 |
Dyskusja:
Najpierw musisz napisać CTE, w którym przypiszesz numer do każdego wiersza w każdej grupie. Aby to zrobić, możesz użyć ROW_NUMBER() funkcjonować. W OVER() , określasz grupy, na które należy podzielić wiersze (PARTITION BY ) oraz kolejność przypisywania numerów do wierszy (ORDER BY ).
Spójrz na wynik wewnętrznego zapytania:
SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results;
| imię | nazwisko | rok | wynik | numer wiersza |
|---|---|---|---|---|
| Jacob | Czarny | 2019 | 44 | 1 |
| Kate | Kowalski | 2019 | 41 | 2 |
| Zaznacz | Johnson | 2019 | 32 | 3 |
| Emilia | Kelly | 2020 | 43 | 1 |
| Edycja | Czarny | 2020 | 43 | 2 |
| Jan | Klein | 2020 | 40 | 3 |
| Tomek | Bennet | 2020 | 38 | 4 |
| Laura | Lato | 2020 | 35 | 5 |
Przypisujesz numery wierszy w każdej grupie (tj. rok). Każdy wiersz ma numer wiersza oparty na wartości result kolumna. Wiersze są sortowane w kolejności malejącej ze względu na DESC słowo kluczowe po ORDER BY result . Nawet jeśli w grupie znajduje się wiele wierszy, które mają tę samą wartość result , wiersze nadal mają różne numery. Tutaj Edith Black i Emily Kelly mają ten sam result ale różne numery wierszy. Aby zmienić to zachowanie i przypisać ten sam numer wiersza dla tego samego wyniku w grupie, użyj RANK() lub DENSE_RANK() zamiast ROW_NUMBER() .
W zapytaniu zewnętrznym wybierasz wszystkie dane z CTE (added_row_number ) i użyj WHERE warunek, aby określić, który wiersz z każdej grupy ma być wyświetlany. Tutaj chcemy wyświetlić pierwszy wiersz, więc warunek to row_number = 1 .
Pamiętaj, że możesz łatwo zmodyfikować rozwiązanie, aby uzyskać na przykład drugi wiersz każdej grupy.
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;
Oto wynik:
| imię | nazwisko | rok | wynik | numer wiersza |
|---|---|---|---|---|
| Kate | Kowalski | 2019 | 41 | 2 |
| Edycja | Czarny | 2020 | 43 | 2 |
Z drugiej strony, jeśli chcesz uzyskać wiersze z drugą najwyższą wartością z result w każdej grupie powinieneś użyć DENSE_RANK() funkcjonować. Podczas gdy ROW_NUMBER() funkcja tworzy kolejne liczby dla każdego wiersza w grupie, co skutkuje różnymi wartościami przypisanymi do wierszy z tym samym wynikiem, DENSE_RANK() funkcja nadaje tę samą liczbę wierszom z tym samym wynikiem.
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;
| imię | nazwisko | rok | wynik | ranking |
|---|---|---|---|---|
| Kate | Kowalski | 2019 | 41 | 2 |
| Jan | Klein | 2020 | 40 | 2 |
Widać, że John Klein ma drugą najwyższą wartość result (40) na rok 2020. John Klein jest w rzeczywistości trzecią osobą w grupie, ale dwóch pierwszych uczniów ma ten sam result i obaj mają rank = 1 .