sql >> Database >  >> RDS >> Database

Hoe de eerste rij in elke GROUP BY Group te selecteren?

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 .


  1. MySQL/MariaDB Vault Database Secrets Engine inrichten met Terraform

  2. Postgres UUID JDBC werkt niet

  3. FORMAT() Voorbeelden in MySQL

  4. Een datum converteren in MySQL vanuit een stringveld