Problem:
Sie haben Ihre Daten mit GROUP BY
gruppiert und möchte nur die erste Zeile aus jeder Gruppe anzeigen.
Beispiel:
Unsere Datenbank hat eine Tabelle namens exam_results
mit Daten in der folgenden Tabelle:
Vorname | Nachname | Jahr | Ergebnis |
---|---|---|---|
Johannes | Klein | 2020 | 40 |
Edith | Schwarz | 2020 | 43 |
Markieren | Johnson | 2019 | 32 |
Laura | Sommer | 2020 | 35 |
Kate | Smith | 2019 | 41 |
Jakob | Schwarz | 2019 | 44 |
Tom | Bennett | 2020 | 38 |
Emily | Kelly | 2020 | 43 |
Lassen Sie uns für jedes Jahr den Schüler mit dem besten result
finden . Wenn es in einer Gruppe zwei gleichberechtigte Schüler gibt, wählen wir willkürlich einen von ihnen zur Anzeige aus.
Lösung:
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;
Das Ergebnis ist:
Vorname | Nachname | Jahr | Ergebnis | Zeilennummer |
---|---|---|---|---|
Jakob | Schwarz | 2019 | 44 | 1 |
Emily | Kelly | 2020 | 43 | 1 |
Diskussion:
Zuerst müssen Sie einen CTE schreiben, in dem Sie jeder Zeile innerhalb jeder Gruppe eine Nummer zuweisen. Dazu können Sie die ROW_NUMBER()
verwenden Funktion. In OVER()
, geben Sie die Gruppen an, in die die Zeilen aufgeteilt werden sollen (PARTITION BY
) und die Reihenfolge, in der die Nummern den Zeilen zugeordnet werden sollen (ORDER BY
).
Sehen Sie sich das Ergebnis der inneren Abfrage an:
SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results;
Vorname | Nachname | Jahr | Ergebnis | Zeilennummer |
---|---|---|---|---|
Jakob | Schwarz | 2019 | 44 | 1 |
Kate | Smith | 2019 | 41 | 2 |
Markieren | Johnson | 2019 | 32 | 3 |
Emily | Kelly | 2020 | 43 | 1 |
Edith | Schwarz | 2020 | 43 | 2 |
Johannes | Klein | 2020 | 40 | 3 |
Tom | Bennett | 2020 | 38 | 4 |
Laura | Sommer | 2020 | 35 | 5 |
Sie weisen die Zeilennummern innerhalb jeder Gruppe (d. h. Jahr) zu. Jede Zeile hat eine Zeilennummer basierend auf dem Wert des result
Säule. Die Zeilen werden aufgrund des DESC
absteigend sortiert Schlüsselwort nach ORDER BY result
. Auch wenn es mehrere Zeilen innerhalb einer Gruppe gibt, die den gleichen Wert von result
haben , erhalten die Zeilen immer noch unterschiedliche Nummern. Hier haben Edith Black und Emily Kelly das gleiche result
aber unterschiedliche Zeilennummern. Um dieses Verhalten zu ändern und dieselbe Zeilennummer für dasselbe Ergebnis innerhalb einer Gruppe zuzuweisen, verwenden Sie RANK()
oder DENSE_RANK()
statt ROW_NUMBER()
.
In der äußeren Abfrage selektieren Sie alle Daten aus dem CTE (added_row_number
) und verwenden Sie ein WHERE
Bedingung, um anzugeben, welche Zeile aus jeder Gruppe angezeigt werden soll. Hier wollen wir die erste Zeile anzeigen, also ist die Bedingung row_number = 1
.
Beachten Sie, dass Sie die Lösung leicht ändern können, um beispielsweise die zweite Reihe zu erhalten jeder Gruppe.
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;
Hier ist das Ergebnis:
Vorname | Nachname | Jahr | Ergebnis | Zeilennummer |
---|---|---|---|---|
Kate | Smith | 2019 | 41 | 2 |
Edith | Schwarz | 2020 | 43 | 2 |
Andererseits, wenn Sie die Zeile(n) mit dem zweithöchsten Wert erhalten möchten von result
Innerhalb jeder Gruppe sollten Sie den DENSE_RANK()
verwenden Funktion. Während die ROW_NUMBER()
-Funktion erstellt fortlaufende Nummern für jede Zeile in einer Gruppe, was dazu führt, dass den Zeilen unterschiedliche Werte mit demselben Ergebnis zugewiesen werden, dem DENSE_RANK()
Funktion gibt den Zeilen mit dem gleichen Ergebnis die gleiche Nummer.
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;
Vorname | Nachname | Jahr | Ergebnis | Rang |
---|---|---|---|---|
Kate | Smith | 2019 | 41 | 2 |
Johannes | Klein | 2020 | 40 | 2 |
Sie können sehen, dass John Klein den zweithöchsten Wert von result (40)
hat für das Jahr 2020. John Klein ist eigentlich die dritte Person in der Gruppe, aber die ersten beiden Schüler haben das gleiche result
und beide haben rank = 1
.