sql >> Databasteknik >  >> RDS >> Database

Hur man väljer den första raden i varje GRUPP FÖR Grupp

Problem:

Du har grupperat dina data med GROUP BY och vill bara visa den första raden från varje grupp.

Exempel:

Vår databas har en tabell som heter exam_results med data i följande tabell:

förnamn efternamn år resultat
John Klein 2020 40
Edith Svart 2020 43
Markera Johnson 2019 32
Laura Sommar 2020 35
Kate Smith 2019 41
Jacob Svart 2019 44
Tom Bennett 2020 38
Emily Kelly 2020 43

För varje år, låt oss hitta studenten med det bästa result . Om det finns två elever som är de bästa i en grupp, väljer vi godtyckligt en av dem att visa.

Lösning:

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;

Resultatet är:

förnamn efternamn år resultat radnummer
Jacob Svart 2019 44 1
Emily Kelly 2020 43 1

Diskussion:

Först måste du skriva en CTE där du tilldelar ett nummer till varje rad inom varje grupp. För att göra det kan du använda ROW_NUMBER() fungera. I OVER() , anger du grupperna som raderna ska delas in i (PARTITION BY ) och i vilken ordning numren ska tilldelas raderna (ORDER BY ).

Ta en titt på resultatet av den inre frågan:

SELECT
  *,
  ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results;
förnamn efternamn år resultat radnummer
Jacob Svart 2019 44 1
Kate Smith 2019 41 2
Markera Johnson 2019 32 3
Emily Kelly 2020 43 1
Edith Svart 2020 43 2
John Klein 2020 40 3
Tom Bennett 2020 38 4
Laura Sommar 2020 35 5

Du tilldelar radnumren inom varje grupp (d.v.s. år). Varje rad har ett radnummer baserat på värdet på result kolumn. Raderna sorteras i fallande ordning på grund av DESC sökord efter ORDER BY result . Även om det finns flera rader inom en grupp som har samma värde på result , raderna får fortfarande olika nummer. Här har Edith Black och Emily Kelly samma result men olika radnummer. För att ändra detta beteende och tilldela samma radnummer för samma resultat inom en grupp, använd RANK() eller DENSE_RANK() istället för ROW_NUMBER() .

I den yttre frågan väljer du all data från CTE (added_row_number ) och använd en WHERE villkor för att ange vilken rad som ska visas från varje grupp. Här vill vi visa den första raden, så villkoret är row_number = 1 .

Observera att du enkelt kan modifiera lösningen för att få till exempel den andra raden för varje grupp.

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;

Här är resultatet:

förnamn efternamn år resultat radnummer
Kate Smith 2019 41 2
Edith Svart 2020 43 2

Å andra sidan, om du vill få raden/raderna med det näst högsta värdet av result inom varje grupp bör du använda DENSE_RANK() fungera. Medan ROW_NUMBER() funktionen skapar på varandra följande tal för varje rad i en grupp, vilket resulterar i olika värden som tilldelas raderna med samma resultat, DENSE_RANK() funktion ger samma nummer till raderna med samma resultat.

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;
förnamn efternamn år resultat rang
Kate Smith 2019 41 2
John Klein 2020 40 2

Du kan se att John Klein har det näst högsta värdet på result (40) för år 2020. John Klein är faktiskt den tredje personen i gruppen, men de två första eleverna har samma result och de har båda rank = 1 .


  1. MySQL Trigger för att förhindra INSERT under vissa förhållanden

  2. Varför kan jag inte använda bindningsvariabler i DDL/SCL-satser i dynamisk SQL?

  3. Oracle PL/SQL-strängjämförelseproblem

  4. Hur man listar alla användare i PostgreSQL