Stell dir vor: Du trackst die Einnahmen deiner Firma, die Verkäufe im Online-Shop oder analysierst einfach deine Ausgaben übers Jahr. Du willst nicht nur sehen, wie viel du jeden Monat eingenommen oder ausgegeben hast, sondern auch, wie sich das Ganze von Monat zu Monat aufsummiert.
Normale Aggregatfunktionen (GROUP BY) helfen uns hier nicht weiter – die gruppieren die Daten und geben nur eine Zeile pro Gruppe zurück. Aber was, wenn wir jeden Monat und gleichzeitig die kumulierte Summe sehen wollen? Genau hier kommt SUM() zusammen mit Window Functions ins Spiel.
Grundlagen: Window Functions für kumulative Summen
Window Functions erlauben es dir, Aggregatfunktionen über Fensterbereiche auszuführen. So kannst du zum Beispiel Werte in jeder Zeile aufsummieren, ohne dass andere Zeilen verschwinden. Kein Opfer mehr für GROUP BY!
Syntax von SUM() mit Window Function
Hier ist das Grundgerüst für eine kumulative Summe:
SELECT
column_name,
SUM(column_name) OVER (PARTITION BY partition_column ORDER BY order_column) AS cumulative_sum
FROM
table_name;
Hier gilt:
SUM(column_name)– summiert die Werte.OVER()– definiert das Fenster für die Berechnung.PARTITION BY– teilt die Daten in Gruppen (optional).ORDER BY– legt die Reihenfolge der Zeilen im Fenster fest.
Beispiel: Kumulierte Einnahmen pro Monat
Stell dir eine Tabelle mit deinen Einnahmen vor:
| monat | einnahme |
|---|---|
| 2023-01 | 1000 |
| 2023-02 | 1500 |
| 2023-03 | 2000 |
Wir wollen die Einnahmen für jeden Monat und die kumulierte Summe sehen. Lass uns ein SQL-Query schreiben:
SELECT
monat,
einnahme,
SUM(einnahme) OVER (ORDER BY monat) AS kumulierte_einnahme
FROM
einnahmen;
Ergebnis:
| monat | einnahme | kumulierte_einnahme |
|---|---|---|
| 2023-01 | 1000 | 1000 |
| 2023-02 | 1500 | 2500 |
| 2023-03 | 2000 | 4500 |
Was passiert hier:
ORDER BY monatimOVER()sagt PostgreSQL, dass die Zeilen chronologisch betrachtet werden sollen.- Für jede Zeile wird die Summe aller vorherigen (und der aktuellen) Zeilen berechnet.
Denk mal drüber nach, was hier abgeht. Für die erste Zeile berechnet SUM() nur die 1. Zeile, für die zweite – die Summe der ersten beiden, für die dritte – die Summe der ersten drei Zeilen. Deshalb ist die Sortierung der Monate so wichtig!
Beispiel: Kumulierte Einnahmen nach Regionen
Wenn du eine Verkaufstabelle nach Regionen hast, könnte ein Ausschnitt so aussehen:
| region | monat | einnahme |
|---|---|---|
| Norden | 2023-01 | 1000 |
| Norden | 2023-02 | 1500 |
| Süden | 2023-01 | 2000 |
| Süden | 2023-02 | 2500 |
Jetzt wollen wir die kumulierten Einnahmen für jede Region einzeln berechnen:
SELECT
region,
monat,
einnahme,
SUM(einnahme) OVER (PARTITION BY region ORDER BY monat) AS kumulierte_einnahme
FROM
verkäufe;
Das Ergebnis sieht dann so aus:
| region | monat | einnahme | kumulierte_einnahme |
|---|---|---|---|
| Norden | 2023-01 | 1000 | 1000 |
| Norden | 2023-02 | 1500 | 2500 |
| Süden | 2023-01 | 2000 | 2000 |
| Süden | 2023-02 | 2500 | 4500 |
Jetzt wird jede Region separat betrachtet (PARTITION BY region), aber innerhalb der Region werden die Zeilen nach Zeit sortiert (ORDER BY monat).
Gleitender Durchschnitt (AVG())
Okay, kumulative Summen sind cool, aber was, wenn du Trends analysieren willst, zum Beispiel für die letzten 3 Monate? Dafür ist der gleitende Durchschnitt perfekt.
Beispiel: Gleitender Durchschnitt der Einnahmen
Wir arbeiten wieder mit der Tabelle einnahmen, hier die Daten:
| monat | einnahme |
|---|---|
| 2023-01 | 1000 |
| 2023-02 | 1500 |
| 2023-03 | 2000 |
| 2023-04 | 2500 |
Query für den 3-Monats-Gleitenden Durchschnitt:
SELECT
monat,
einnahme,
AVG(einnahme) OVER (
ORDER BY monat
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS gleitender_durchschnitt
FROM
einnahmen;
Ergebnis:
| monat | einnahme | gleitender_durchschnitt |
|---|---|---|
| 2023-01 | 1000 | 1000 |
| 2023-02 | 1500 | 1250 |
| 2023-03 | 2000 | 1500 |
| 2023-04 | 2500 | 2000 |
Erklärung:
ROWS BETWEEN 2 PRECEDING AND CURRENT ROWsagt PostgreSQL, dass für den Durchschnitt die aktuelle und zwei vorherige Zeilen betrachtet werden.- So siehst du für jeden Monat den Durchschnitt der letzten 3 Monate.
Das heißt, für jede Zeile definieren wir ein Fenster von 3 Zeilen: die aktuelle und die zwei davor. Dann berechnen wir daraus den Durchschnitt. Super praktisch.
Wie ORDER BY wirkt
Window Functions hängen stark von der richtigen Reihenfolge der Zeilen ab. Wenn die Reihenfolge falsch (oder gar nicht) angegeben ist, können die Ergebnisse ziemlich schräg sein.
Beispiel: Fehler ohne ORDER BY
Wenn wir ORDER BY aus OVER() rauslassen, bekommen wir statt der kumulierten Summe einfach die Gesamtsumme für jede Zeile:
SELECT
monat,
einnahme,
SUM(einnahme) OVER () AS falsche_kumulative_summe
FROM
einnahmen;
Ergebnis:
| monat | einnahme | falschekumulativesumme |
|---|---|---|
| 2023-01 | 1000 | 7000 |
| 2023-02 | 1500 | 7000 |
| 2023-03 | 2000 | 7000 |
| 2023-04 | 2500 | 7000 |
Die Zeilen sind nicht sortiert, und statt einer kumulierten Summe wird einfach die Gesamtsumme für alle Zeilen berechnet.
Echte Use Cases
Einnahmen-Analyse:
- Kumulative Summen zeigen, wie die Verkäufe oder Einnahmen der Firma wachsen.
- Gleitende Durchschnitte helfen, den "echten" Trend ohne Ausreißer zu sehen.
Finanzmodellierung:
Banks und Finanzunternehmen nutzen Window Functions, um Zahlungen, Schuldenwachstum und andere Metriken zu analysieren.
Zeitreihen-Analyse:
Zeitbasierte Daten wie Online-User, Seitenaufrufe, Umsatz usw. lassen sich mit SUM() und AVG() perfekt analysieren.
GO TO FULL VERSION