Probleem:
U heeft uw gegevens gegroepeerd met GROUP BY
en wil alleen de eerste rij van elke groep weergeven.
Voorbeeld:
Onze database heeft een tabel met de naam exam_results
met gegevens in de volgende tabel:
voornaam | achternaam | jaar | resultaat |
---|---|---|---|
Jan | Klein | 2020 | 40 |
Edith | Zwart | 2020 | 43 |
Markeren | Johnson | 2019 | 32 |
Laura | Zomer | 2020 | 35 |
Kate | Smith | 2019 | 41 |
Jacob | Zwart | 2019 | 44 |
Tom | Bennett | 2020 | 38 |
Emily | Kelly | 2020 | 43 |
Laten we voor elk jaar de leerling vinden met het beste result
. Als er twee studenten gelijk zijn in een groep, zullen we willekeurig een van hen selecteren om weer te geven.
Oplossing:
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;
Het resultaat is:
voornaam | achternaam | jaar | resultaat | rijnummer |
---|---|---|---|---|
Jacob | Zwart | 2019 | 44 | 1 |
Emily | Kelly | 2020 | 43 | 1 |
Discussie:
Eerst moet u een CTE schrijven waarin u een nummer toewijst aan elke rij binnen elke groep. Om dat te doen, kunt u de ROW_NUMBER()
. gebruiken functie. In OVER()
, specificeert u de groepen waarin de rijen moeten worden verdeeld (PARTITION BY
) en de volgorde waarin de nummers aan de rijen moeten worden toegewezen (ORDER BY
).
Bekijk het resultaat van de inner query:
SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results;
voornaam | achternaam | jaar | resultaat | rijnummer |
---|---|---|---|---|
Jacob | Zwart | 2019 | 44 | 1 |
Kate | Smith | 2019 | 41 | 2 |
Markeren | Johnson | 2019 | 32 | 3 |
Emily | Kelly | 2020 | 43 | 1 |
Edith | Zwart | 2020 | 43 | 2 |
Jan | Klein | 2020 | 40 | 3 |
Tom | Bennett | 2020 | 38 | 4 |
Laura | Zomer | 2020 | 35 | 5 |
U wijst de rijnummers toe binnen elke groep (d.w.z. jaar). Elke rij heeft een rijnummer gebaseerd op de waarde van het result
kolom. De rijen zijn in aflopende volgorde gesorteerd vanwege de DESC
trefwoord na ORDER BY result
. Zelfs als er meerdere rijen binnen een groep zijn die dezelfde waarde hebben van result
, krijgen de rijen nog steeds verschillende nummers. Hier hebben Edith Black en Emily Kelly hetzelfde result
maar verschillende rijnummers. Gebruik RANK()
om dit gedrag te wijzigen en hetzelfde rijnummer toe te wijzen aan hetzelfde resultaat binnen een groep. of DENSE_RANK()
in plaats van ROW_NUMBER()
.
In de buitenste query selecteert u alle gegevens van de CTE (added_row_number
) en gebruik een WHERE
voorwaarde om aan te geven welke rij van elke groep moet worden weergegeven. Hier willen we de eerste rij weergeven, dus de voorwaarde is row_number = 1
.
Merk op dat u de oplossing eenvoudig kunt aanpassen om bijvoorbeeld de tweede rij . te krijgen van elke groep.
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;
Dit is het resultaat:
voornaam | achternaam | jaar | resultaat | rijnummer |
---|---|---|---|---|
Kate | Smith | 2019 | 41 | 2 |
Edith | Zwart | 2020 | 43 | 2 |
Aan de andere kant, als u de rij(en) wilt krijgen met de op één na hoogste waarde van result
binnen elke groep moet u de DENSE_RANK()
. gebruiken functie. Terwijl de ROW_NUMBER()
functie creëert opeenvolgende nummers voor elke rij in een groep, wat resulteert in verschillende waarden die aan de rijen worden toegewezen met hetzelfde resultaat, de DENSE_RANK()
functie geeft hetzelfde nummer aan de rijen met hetzelfde resultaat.
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;
voornaam | achternaam | jaar | resultaat | rang |
---|---|---|---|---|
Kate | Smith | 2019 | 41 | 2 |
Jan | Klein | 2020 | 40 | 2 |
Je kunt zien dat John Klein de op één na hoogste waarde heeft van result (40)
voor het jaar 2020. John Klein is eigenlijk de derde persoon in de groep, maar de eerste twee studenten hebben hetzelfde result
en ze hebben allebei rank = 1
.