Stell dir vor, du arbeitest als Kellner (oder Barista, falls du Kaffee magst) in einem großen Restaurant. Jeden Tag ziehst du Bilanz über das verdiente Trinkgeld. Aber es gibt einen Haken: Das Restaurant ist in Zonen aufgeteilt, und dich interessiert, wie viel Trinkgeld in jeder Zone einzeln verdient wurde. PARTITION BY ist das, was SQL benutzt, um das "Restaurant in Zonen zu teilen".
Formeller gesagt, PARTITION BY wird in Window Functions verwendet, um alle Zeilen einer Tabelle in einzelne Gruppen (oder "Partitionen") zu teilen. Innerhalb jeder Gruppe wird die Window Function neu ausgeführt. Das ist so, als würdest du die Funktion separat in jedem "Abschnitt" anwenden.
Beispiel: Wie das funktioniert
Nehmen wir an, wir haben eine Tabelle sales mit Verkaufsdaten:
| region | salesperson | amount |
|---|---|---|
| North | Alice | 100 |
| North | Bob | 200 |
| South | Alice | 150 |
| South | Charlie | 250 |
Wenn wir berechnen wollen, wie viel Geld jeder Verkäufer verdient hat, aber getrennt für jede Region, dann ist PARTITION BY genau das, was wir brauchen.
Syntax von PARTITION BY
Die Syntax ist ziemlich easy:
window_function() OVER (PARTITION BY spalte_oder_spalten)
window_function()— das ist zum BeispielSUM(),AVG(),ROW_NUMBER()und so weiter.PARTITION BY spalte— gibt an, nach welcher Spalte die Zeilen aufgeteilt werden sollen.OVER()— das ist der Operator, der SQL sagt: "Mach das innerhalb des angegebenen Fensters".
Beispiel: Summe pro Gruppe
Lass uns die Verkaufssumme für jede Region berechnen:
SELECT
region,
salesperson,
amount,
SUM(amount) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales;
Das Ergebnis sieht so aus:
| region | salesperson | amount | total_sales_by_region |
|---|---|---|---|
| North | Alice | 100 | 300 |
| North | Bob | 200 | 300 |
| South | Alice | 150 | 400 |
| South | Charlie | 250 | 400 |
Was passiert hier? SQL teilt die Zeilen in Gruppen nach dem Wert der Spalte region (North und South) auf und wendet dann die Funktion SUM() separat für jede Gruppe an. Das Ergebnis ist, dass die Zeilen in der Gruppe "North" denselben Summenwert bekommen und die Zeilen in "South" einen anderen.
Beispiele für die Verwendung von PARTITION BY
Schauen wir uns an, wie PARTITION BY in echten Aufgaben nützlich sein kann.
Beispiel 1: Ranking innerhalb einer Gruppe
Angenommen, wir wollen die Verkäufer innerhalb jeder Region nach Verkaufsmenge ranken. Dafür kann man PARTITION BY zusammen mit der Funktion RANK() verwenden:
SELECT
region,
salesperson,
amount,
RANK() OVER (PARTITION BY region ORDER BY amount DESC) AS rank_in_region
FROM sales;
Das Ergebnis:
| region | salesperson | amount | rank_in_region |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
Die Funktion RANK() vergibt einen Rang innerhalb jeder region-Gruppe, beginnend bei 1. Beachte, dass die Ränge für jede Gruppe bei eins starten.
Beispiel 2: Jeden Wert mit dem Durchschnitt der Gruppe vergleichen
Angenommen, wir wollen sehen, wie viel jeder Verkäufer im Vergleich zum Durchschnitt seiner Region verdient hat. Wir benutzen AVG():
SELECT
region,
salesperson,
amount,
AVG(amount) OVER (PARTITION BY region) AS avg_sales_by_region,
amount - AVG(amount) OVER (PARTITION BY region) AS diff_from_avg
FROM sales;
Das Ergebnis:
| region | salesperson | amount | avg_sales_by_region | diff_from_avg |
|---|---|---|---|---|
| North | Alice | 100 | 150 | -50 |
| North | Bob | 200 | 150 | 50 |
| South | Alice | 150 | 200 | -50 |
| South | Charlie | 250 | 200 | 50 |
Zuerst teilt SQL die Zeilen nach region in Gruppen. Dann berechnet es den Durchschnitt AVG(amount) für jede Gruppe. Schließlich wird für jede Zeile die Differenz zwischen ihrem Wert und dem Durchschnitt berechnet.
Beispiel 3: Zeilennummerierung innerhalb einer Gruppe
Sagen wir, du willst alle Transaktionen innerhalb jeder Region durchnummerieren. Wir nutzen ROW_NUMBER():
SELECT
region,
salesperson,
amount,
ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS row_number
FROM sales;
Das Ergebnis:
| region | salesperson | amount | row_number |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
Vergleich mit GROUP BY
Oft gibt es Verwirrung zwischen PARTITION BY und GROUP BY. Lass uns die beiden vergleichen:
GROUP BY
GROUP BY verändert die Struktur des Ergebnisses — es verwandelt die Zeilen der Tabelle in Aggregate. Zum Beispiel:
SELECT
region,
SUM(amount) AS total_sales
FROM sales
GROUP BY region;
Das Ergebnis:
| region | total_sales |
|---|---|
| North | 300 |
| South | 400 |
Hier verlieren wir die Info über die Verkäufer, weil die Daten aggregiert werden.
PARTITION BY
PARTITION BY dagegen verändert die Struktur nicht. Wir sehen immer noch jede Zeile, aber haben zusätzliche Werte, die pro Gruppe berechnet wurden. Das heißt, PARTITION BY erlaubt Aggregation ohne Detailverlust.
Häufige Fehler bei der Verwendung von PARTITION BY
Fehler 1: PARTITION BY vergessen
Manchmal willst du Daten gruppieren, vergisst aber PARTITION BY zu benutzen. Zum Beispiel:
SELECT
region,
salesperson,
amount,
SUM(amount) OVER () AS total_sales
FROM sales;
Das Ergebnis:
| region | salesperson | amount | total_sales |
|---|---|---|---|
| North | Alice | 100 | 700 |
| North | Bob | 200 | 700 |
| South | Alice | 150 | 700 |
| South | Charlie | 250 | 700 |
Hier wird SUM(amount) für die ganze Tabelle berechnet, nicht getrennt nach Regionen. Wenn du Regionen berücksichtigen willst, vergiss nicht PARTITION BY region anzugeben.
Fehler 2: Falsche Reihenfolge im ORDER BY
Die Reihenfolge der Zeilen im Fenster ist wichtig für Funktionen wie RANK() oder ROW_NUMBER(). Sei aufmerksam, wenn du ORDER BY innerhalb von OVER() benutzt.
GO TO FULL VERSION