Wie berechnet man Zwischensummen in SQL?
ROLLUP und CUBE sind Erweiterungen von GROUP BY. Sie liefern Summen auf mehreren Ebenen in einer Abfrage: je Filiale und Produkt, je Filiale und insgesamt.
So ersetzen Sie drei Abfragen durch eine. Der Bericht hat dann Zwischensummen und eine Gesamtsumme.
Am Ende dieser Lektion
Notiz
Ich kann in einer Abfrage Summen auf mehreren Ebenen berechnen.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Zwischensumme | die Summe einer Gruppe innerhalb einer größeren Gruppe | |
| ROLLUP | bildet Summen für jede Ebene von der feinsten bis zur Gesamtsumme | |
| CUBE | bildet Summen für jede Kombination der Spalten | |
| FILTER | lässt eine Aggregatfunktion nur ausgewählte Zeilen zählen | sum(x) filter (where y = 1) |
| Kreuztabelle | macht aus den Werten einer Spalte eigene Spalten |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Rollup fügt Zwischensummen und die Gesamtsumme hinzu
Ein gewöhnliches group by filiale, produkt gibt eine Zeile je Paar. Eine Zwischensumme je Filiale fehlt.
group by rollup(filiale, produkt) rollt die Spalten von rechts nach links auf: erst je Filiale und Produkt, dann je Filiale allein, dann alles zusammen.
In den Zusatzzeilen steht NULL für die Spalte, die zusammengefasst wurde.
Ein Ausschnitt des Ergebnisses
| filiale | produkt | umsatz_euro | Ebene |
|---|---|---|---|
| Berlin | Kaffee | 66 | Filiale und Produkt |
| Berlin | NULL | 95 | Zwischensumme Berlin |
| Hamburg | NULL | 93 | Zwischensumme Hamburg |
| NULL | NULL | 340 | Gesamtsumme |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Probieren Sie es: Rollup über zwei Spalten
-- Je Filiale und Produkt, je Filiale, und insgesamt.
select filiale, produkt, sum(betrag_euro) as umsatz_euro
from verkaeufe
group by rollup(filiale, produkt)
order by filiale nulls last, produkt nulls last;
-- Vertauschen Sie die Reihenfolge: rollup(produkt, filiale).
NULL in einer Summenzeile heißt alle
Ein NULL in einer Zusatzzeile sagt nicht, dass ein Wert fehlt. Es sagt, dass diese Spalte über alle Werte zusammengefasst wurde.
Für den Bericht schreiben Sie ein Wort hin: coalesce(produkt, 'alle Produkte') ersetzt NULL durch den Text.
Hat Ihre Tabelle echte NULL-Werte, nutzen Sie grouping(produkt): Es ist 1 in einer Summenzeile und sonst 0.
Probieren Sie es: die Summenzeilen beschriften
-- NULL steht hier für "alle"; coalesce schreibt das Wort hin.
select filiale, coalesce(produkt, 'alle Produkte') as produkt,
sum(betrag_euro) as umsatz_euro
from verkaeufe
group by rollup(filiale, produkt)
order by filiale nulls last, produkt;
Ein häufiger Fehler
Warnung
Viele lesen das NULL einer Summenzeile als fehlenden Wert. Es ist ein Zeichen für alle Werte. Gibt es in Ihren Daten auch echte NULL, trennt nur grouping() die beiden Fälle sicher.
Cube bildet jede Kombination
rollup kennt eine Reihenfolge: erst die Filiale, dann das Produkt. Eine Summe je Produkt über alle Filialen gibt es dort nicht.
cube(filiale, produkt) bildet alle Kombinationen: beide Spalten, nur Filiale, nur Produkt und keine.
Das sind vier Ebenen statt drei. Bei vielen Spalten wächst die Zahl schnell.
Probieren Sie es: Cube über zwei Spalten
-- Cube bildet auch die Summe je Produkt über alle Filialen.
select filiale, produkt, sum(betrag_euro) as umsatz_euro
from verkaeufe
group by cube(filiale, produkt)
order by filiale nulls last, produkt nulls last;
Filter und eine Kreuztabelle von Hand
filter (where ...) hinter einer Aggregatfunktion lässt sie nur Zeilen zählen, die die Bedingung erfüllen.
Mit einem filter je Produkt entsteht eine Kreuztabelle: Die Produkte stehen nebeneinander als Spalten, die Filialen untereinander.
So ist ein Pivot von Hand geschrieben, ganz ohne Spezialsyntax.
Probieren Sie es: ein Pivot mit filter
-- Eine Spalte je Produkt, gezählt mit filter.
select filiale,
sum(betrag_euro) as gesamt,
sum(betrag_euro) filter (where produkt = 'Kaffee') as kaffee,
sum(betrag_euro) filter (where produkt = 'Tee') as tee,
sum(betrag_euro) filter (where produkt = 'Kakao') as kakao
from verkaeufe
group by filiale
order by filiale;
-- Fügen Sie eine Spalte nur für den 3. März hinzu.