Mit ROLLUP, CUBE und GROUPING SETS lassen sich in Oracle SQL mehrere Aggregationsebenen innerhalb einer einzigen Abfrage berechnen. Dadurch können Detailwerte, Zwischensummen und Gesamtsummen gemeinsam ausgegeben werden.
Die drei Erweiterungen verfolgen unterschiedliche Ziele:
ROLLUPerzeugt hierarchisch aufgebaute Zwischensummen.CUBEberechnet alle Kombinationen der angegebenen Gruppierungsmerkmale.GROUPING SETSbeschränkt die Ausgabe auf ausdrücklich festgelegte Gruppierungen.GROUPINGundGROUPING_IDzeigen, zu welcher Aggregationsebene eine Ergebniszeile gehört.
Dieser Artikel erklärt die Unterschiede anhand vollständiger Testdaten und ausführbarer Oracle-SQL-Abfragen.
Testdaten für die Beispiele
Für die folgenden Beispiele wird eine vereinfachte Umsatztabelle verwendet. Sie enthält Umsätze nach Land, Stadt und Produkt.
CREATE TABLE umsatz_daten (
umsatz_id NUMBER NOT NULL,
buchungsdatum DATE NOT NULL,
land VARCHAR2(30),
stadt VARCHAR2(30),
produkt VARCHAR2(50),
betrag NUMBER(12, 2) NOT NULL,
CONSTRAINT pk_umsatz_daten PRIMARY KEY (umsatz_id)
);
Die Testdaten können mit INSERT ALL eingefügt werden:
INSERT ALL
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(1, DATE '2026-01-10', 'Österreich', 'Graz', 'Laptop', 1000)
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(2, DATE '2026-01-12', 'Österreich', 'Graz', 'Monitor', 500)
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(3, DATE '2026-01-15', 'Österreich', 'Wien', 'Laptop', 1500)
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(4, DATE '2026-01-20', 'Österreich', 'Wien', 'Monitor', 700)
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(5, DATE '2026-01-17', 'Deutschland', 'München', 'Laptop', 1200)
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(6, DATE '2026-01-22', 'Deutschland', 'München', 'Monitor', 600)
INTO umsatz_daten
(umsatz_id, buchungsdatum, land, stadt, produkt, betrag)
VALUES
(7, DATE '2026-01-25', 'Deutschland', 'Berlin', 'Laptop', 900)
SELECT 1
FROM dual;
COMMIT;
Die Tabelle enthält insgesamt einen Umsatz von 6.400.
Nach Ländern ergeben sich:
| Land | Umsatz |
|---|---|
| Österreich | 3.700 |
| Deutschland | 2.700 |
| Gesamtsumme | 6.400 |
Nach Produkten ergeben sich:
| Produkt | Umsatz |
| Laptop | 4.600 |
| Monitor | 1.800 |
| Gesamtsumme | 6.400 |
Normale Aggregation mit GROUP BY
Eine gewöhnliche GROUP BY-Abfrage liefert nur die ausdrücklich angegebene Gruppierungsebene.
SELECT
land,
stadt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY
land,
stadt
ORDER BY
land,
stadt;
Das Ergebnis enthält eine Zeile je Kombination aus Land und Stadt:
| LAND | STADT | UMSATZ |
| Deutschland | Berlin | 900 |
| Deutschland | München | 1.800 |
| Österreich | Graz | 1.500 |
| Österreich | Wien | 2.200 |
Eine Zwischensumme pro Land oder eine Gesamtsumme wird nicht erzeugt.
Dafür müssten ohne ROLLUP mehrere Abfragen miteinander verbunden werden. Ein typischer, aber aufwendiger Ansatz wäre:
SELECT
land,
stadt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY
land,
stadt
UNION ALL
SELECT
land,
NULL AS stadt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY
land
UNION ALL
SELECT
NULL AS land,
NULL AS stadt,
SUM(betrag) AS umsatz
FROM umsatz_daten;
ROLLUP erzeugt dieselben Aggregationsebenen wesentlich übersichtlicher.
Zwischensummen mit ROLLUP erzeugen
ROLLUP bildet eine hierarchische Aggregation. Die Gruppierung wird von rechts nach links schrittweise reduziert.
SELECT
land,
stadt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY ROLLUP(land, stadt)
ORDER BY
GROUPING(land),
land,
GROUPING(stadt),
stadt;
Die Abfrage erzeugt drei Ebenen:
- Umsatz nach Land und Stadt
- Zwischensumme nach Land
- Gesamtsumme über alle Datensätze
Das Ergebnis sieht vereinfacht so aus:
| LAND | STADT | UMSATZ |
| Deutschland | Berlin | 900 |
| Deutschland | München | 1.800 |
| Deutschland | NULL | 2.700 |
| Österreich | Graz | 1.500 |
| Österreich | Wien | 2.200 |
| Österreich | NULL | 3.700 |
| NULL | NULL | 6.400 |
Die Zeilen mit einer leeren Stadt sind die Zwischensummen der jeweiligen Länder.
Die letzte Zeile, in der sowohl Land als auch Stadt leer sind, ist die Gesamtsumme.
Warum die Reihenfolge bei ROLLUP wichtig ist
Die Reihenfolge der Spalten innerhalb von ROLLUP bestimmt die erzeugte Hierarchie.
GROUP BY ROLLUP(land, stadt)
entspricht inhaltlich folgenden Gruppierungen:
(land, stadt)
(land)
()
Die leeren Klammern stehen für die Gesamtsumme.
Die umgekehrte Reihenfolge:
GROUP BY ROLLUP(stadt, land)
erzeugt dagegen:
(stadt, land)
(stadt)
()
Dabei werden Zwischensummen nach Stadt und nicht nach Land gebildet.
Bei hierarchischen Daten muss deshalb zuerst die übergeordnete und danach die untergeordnete Ebene angegeben werden.
Beispiele:
Jahr, Monat, Tag
Land, Region, Stadt
Abteilung, Team, Mitarbeiter
Produktgruppe, Produkt
Drei Aggregationsebenen mit ROLLUP
ROLLUP kann mehr als zwei Spalten verarbeiten.
SELECT
land,
stadt,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY ROLLUP(
land,
stadt,
produkt
)
ORDER BY
GROUPING(land),
land,
GROUPING(stadt),
stadt,
GROUPING(produkt),
produkt;
Diese Abfrage erzeugt:
Land, Stadt und Produkt
Land und Stadt
Land
Gesamtsumme
Für Österreich und Graz entstehen beispielsweise:
| LAND | STADT | PRODUKT | UMSATZ |
| Österreich | Graz | Laptop | 1.000 |
| Österreich | Graz | Monitor | 500 |
| Österreich | Graz | NULL | 1.500 |
Danach folgen die weiteren Städte, die Zwischensumme für Österreich und abschließend die Gesamtsumme.
Künstliche NULL-Werte mit GROUPING erkennen
ROLLUP und CUBE verwenden NULL, um zusammengefasste Dimensionen darzustellen.
Ein NULL in einer Summenzeile bedeutet beispielsweise:
Alle Städte
Alle Produkte
Alle Länder
Das ist nicht dasselbe wie ein tatsächlich in der Tabelle gespeicherter NULL-Wert.
Die Funktion GROUPING unterscheidet beide Fälle.
GROUPING(land)
liefert:
0 = normaler Gruppenwert oder tatsächlich gespeichertes NULL
1 = von ROLLUP, CUBE oder GROUPING SETS erzeugte Summierung
Damit lassen sich verständliche Beschriftungen erzeugen:
SELECT
CASE
WHEN GROUPING(land) = 1
THEN 'Alle Länder'
ELSE NVL(land, 'Land unbekannt')
END AS land,
CASE
WHEN GROUPING(stadt) = 1
THEN 'Alle Städte'
ELSE NVL(stadt, 'Stadt unbekannt')
END AS stadt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY ROLLUP(land, stadt)
ORDER BY
GROUPING(land),
land,
GROUPING(stadt),
stadt;
Das Ergebnis ist leichter verständlich:
| LAND | STADT | UMSATZ |
| Deutschland | Berlin | 900 |
| Deutschland | München | 1.800 |
| Deutschland | Alle Städte | 2.700 |
| Österreich | Graz | 1.500 |
| Österreich | Wien | 2.200 |
| Österreich | Alle Städte | 3.700 |
| Alle Länder | Alle Städte | 6.400 |
Eine Prüfung mit:
land IS NULL
kann nicht unterscheiden, ob der Wert tatsächlich gespeichert wurde oder durch die Aggregation entstanden ist.
Dafür muss GROUPING(land) verwendet werden.
Tatsächliches NULL und Summenzeile unterscheiden
Das folgende Beispiel enthält bewusst einen Datensatz ohne Land:
WITH daten AS (
SELECT
CAST(NULL AS VARCHAR2(30)) AS land,
100 AS betrag
FROM dual
UNION ALL
SELECT
'Österreich',
200
FROM dual
)
SELECT
CASE
WHEN GROUPING(land) = 1
THEN 'Alle Länder'
WHEN land IS NULL
THEN 'Land unbekannt'
ELSE land
END AS land,
SUM(betrag) AS betrag
FROM daten
GROUP BY ROLLUP(land);
Das Ergebnis enthält drei unterschiedliche Zeilen:
| LAND | BETRAG |
| Land unbekannt | 100 |
| Österreich | 200 |
| Alle Länder | 300 |
Ohne GROUPING könnten die Zeile „Land unbekannt“ und die Gesamtsumme nicht zuverlässig unterschieden werden.
Alle Kombinationen mit CUBE berechnen
CUBE erzeugt alle möglichen Kombinationen der angegebenen Gruppierungsmerkmale.
SELECT
land,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY CUBE(land, produkt);
Bei zwei Gruppierungsspalten entstehen vier Aggregationsebenen:
(land, produkt)
(land)
(produkt)
()
Damit liefert die Abfrage:
- Umsatz je Land und Produkt
- Umsatz je Land
- Umsatz je Produkt
- Gesamtsumme
Mit verständlichen Beschriftungen:
SELECT
CASE
WHEN GROUPING(land) = 1
THEN 'Alle Länder'
ELSE land
END AS land,
CASE
WHEN GROUPING(produkt) = 1
THEN 'Alle Produkte'
ELSE produkt
END AS produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY CUBE(land, produkt)
ORDER BY
GROUPING_ID(land, produkt),
land NULLS LAST,
produkt NULLS LAST;
Das Ergebnis:
| LAND | PRODUKT | UMSATZ |
| Deutschland | Laptop | 2.100 |
| Deutschland | Monitor | 600 |
| Österreich | Laptop | 2.500 |
| Österreich | Monitor | 1.200 |
| Deutschland | Alle Produkte | 2.700 |
| Österreich | Alle Produkte | 3.700 |
| Alle Länder | Laptop | 4.600 |
| Alle Länder | Monitor | 1.800 |
| Alle Länder | Alle Produkte | 6.400 |
Unterschied zwischen ROLLUP und CUBE
Bei zwei Spalten erzeugt ROLLUP drei Gruppierungen:
GROUP BY ROLLUP(land, produkt)
entspricht:
(land, produkt)
(land)
()
Eine produktübergreifende Auswertung ohne Land wird nicht erzeugt.
CUBE erzeugt dagegen vier Gruppierungen:
GROUP BY CUBE(land, produkt)
entspricht:
(land, produkt)
(land)
(produkt)
()
Damit kommt zusätzlich die Aggregation nur nach Produkt hinzu.
ROLLUP eignet sich für Hierarchien. CUBE eignet sich für Dimensionen, die unabhängig voneinander ausgewertet werden sollen.
Aggregationsebenen mit GROUPING_ID erkennen
Bei mehreren Gruppierungsspalten werden mehrere Aufrufe von GROUPING schnell unübersichtlich.
GROUPING(land)
GROUPING(produkt)
GROUPING_ID fasst diese Informationen in einer Zahl zusammen:
GROUPING_ID(land, produkt)
Bei zwei Spalten ergeben sich folgende Werte:
| LAND aggregiert | PRODUKT aggregiert | Bitmuster | GROUPING_ID |
| 0 | 0 | 00 | 0 |
| 0 | 1 | 01 | 1 |
| 1 | 0 | 10 | 2 |
| 1 | 1 | 11 | 3 |
Damit gilt:
0 = Detailgruppe nach Land und Produkt
1 = Zwischensumme nach Land
2 = Zwischensumme nach Produkt
3 = Gesamtsumme
Die Gruppierungsnummer kann direkt ausgegeben werden:
SELECT
land,
produkt,
SUM(betrag) AS umsatz,
GROUPING_ID(land, produkt) AS gruppierung
FROM umsatz_daten
GROUP BY CUBE(land, produkt)
ORDER BY
gruppierung,
land,
produkt;
Bestimmte Summenebenen filtern
Mit GROUPING_ID können bestimmte Aggregationsebenen gezielt ausgewählt werden.
Nur Zwischensummen nach Land und die Gesamtsumme:
SELECT
land,
produkt,
SUM(betrag) AS umsatz,
GROUPING_ID(land, produkt) AS gruppierung
FROM umsatz_daten
GROUP BY CUBE(land, produkt)
HAVING GROUPING_ID(land, produkt) IN (1, 3)
ORDER BY
gruppierung,
land;
Das Ergebnis:
| LAND | PRODUKT | UMSATZ | GRUPPIERUNG |
| Deutschland | NULL | 2.700 | 1 |
| Österreich | NULL | 3.700 | 1 |
| NULL | NULL | 6.400 | 3 |
Nur die Gesamtsumme:
HAVING GROUPING_ID(land, produkt) = 3
Alle Summenzeilen, aber keine Detailzeilen:
HAVING GROUPING_ID(land, produkt) > 0
Nur benötigte Gruppierungen mit GROUPING SETS berechnen
Ein vollständiger CUBE erzeugt auch Gruppierungen, die möglicherweise gar nicht benötigt werden.
Angenommen, ein Bericht soll nur diese Ebenen enthalten:
- Land und Produkt
- Zwischensumme je Land
- Gesamtsumme
Eine reine Produktaggregation wird nicht benötigt.
Dafür eignet sich GROUPING SETS:
SELECT
land,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY GROUPING SETS (
(land, produkt),
(land),
()
)
ORDER BY
GROUPING_ID(land, produkt),
land,
produkt;
Die einzelnen Einträge bedeuten:
(land, produkt)
Gruppierung nach Land und Produkt.
(land)
Zwischensumme je Land.
()
Gesamtsumme.
Das Ergebnis enthält keine Gruppierung nur nach Produkt.
| LAND | PRODUKT | UMSATZ |
| Deutschland | Laptop | 2.100 |
| Deutschland | Monitor | 600 |
| Österreich | Laptop | 2.500 |
| Österreich | Monitor | 1.200 |
| Deutschland | NULL | 2.700 |
| Österreich | NULL | 3.700 |
| NULL | NULL | 6.400 |
GROUPING SETS ist deshalb sinnvoll, wenn ein Bericht nur bestimmte Aggregationsebenen benötigt.
GROUPING SETS statt mehrerer UNION-ALL-Abfragen
Ohne GROUPING SETS könnte derselbe Bericht mit mehreren Abfragen erstellt werden:
SELECT
land,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY
land,
produkt
UNION ALL
SELECT
land,
NULL AS produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY
land
UNION ALL
SELECT
NULL AS land,
NULL AS produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten;
Diese Variante ist länger und fehleranfälliger. Änderungen an Filtern oder Berechnungen müssen in allen Teilabfragen konsistent vorgenommen werden.
Mit GROUPING SETS wird die fachliche Struktur direkt in einer einzigen GROUP BY-Klausel beschrieben.
Partielles ROLLUP verwenden
Nicht immer soll eine Gesamtsumme über sämtliche Daten entstehen.
Mit:
GROUP BY
land,
ROLLUP(stadt, produkt)
bleibt land Bestandteil jeder Gruppierung.
Die vollständige Abfrage:
SELECT
land,
stadt,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY
land,
ROLLUP(stadt, produkt)
ORDER BY
land,
GROUPING(stadt),
stadt,
GROUPING(produkt),
produkt;
Sie erzeugt:
(land, stadt, produkt)
(land, stadt)
(land)
Eine Gesamtsumme ohne Land entsteht nicht.
Das ist sinnvoll, wenn beispielsweise für jedes Unternehmen, Mandantengebiet oder Land ein getrennter Bericht erzeugt wird, aber keine gemeinsame Gesamtsumme gewünscht ist.
Der Unterschied lautet:
GROUP BY ROLLUP(land, stadt, produkt)
erzeugt zusätzlich:
()
also eine Gesamtsumme.
Dagegen erzeugt:
GROUP BY land, ROLLUP(stadt, produkt)
keine landübergreifende Gesamtsumme.
WHERE und HAVING richtig einsetzen
WHERE filtert Datensätze vor der Aggregation.
HAVING filtert das bereits aggregierte Ergebnis.
Beispiel für Umsätze aus dem Januar 2026:
SELECT
land,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
WHERE buchungsdatum >= DATE '2026-01-01'
AND buchungsdatum < DATE '2026-02-01'
GROUP BY ROLLUP(land, produkt);
Die Datumsbedingung gehört in die WHERE-Klausel, weil nur bestimmte Ausgangsdatensätze berücksichtigt werden sollen.
Sollen dagegen nur Aggregationen ab einem Umsatz von 1.000 angezeigt werden, wird HAVING verwendet:
SELECT
land,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
GROUP BY ROLLUP(land, produkt)
HAVING SUM(betrag) >= 1000;
Beide Bedingungen können kombiniert werden:
SELECT
land,
produkt,
SUM(betrag) AS umsatz
FROM umsatz_daten
WHERE buchungsdatum >= DATE '2026-01-01'
AND buchungsdatum < DATE '2026-02-01'
GROUP BY ROLLUP(land, produkt)
HAVING SUM(betrag) >= 1000;
Summenzeilen richtig sortieren
Ohne passende ORDER BY-Klausel ist die Reihenfolge der Ergebniszeilen nicht garantiert.
Eine verständliche Sortierung für ROLLUP ist:
ORDER BY
GROUPING(land),
land,
GROUPING(stadt),
stadt
Dadurch erscheinen:
- Detailzeilen des Landes
- Zwischensumme des Landes
- Gesamtsumme
Alternativ kann GROUPING_ID verwendet werden:
ORDER BY
GROUPING_ID(land, stadt),
land,
stadt
Bei komplexen Berichten kann eine eigene Sortierspalte erzeugt werden:
CASE GROUPING_ID(land, produkt)
WHEN 0 THEN 1
WHEN 1 THEN 2
WHEN 2 THEN 3
WHEN 3 THEN 4
END AS sortierung
Diese Spalte kann anschließend für die gewünschte Reihenfolge verwendet werden.
Typische Fehler bei ROLLUP, CUBE und GROUPING SETS
Die Reihenfolge innerhalb von ROLLUP ist falsch
ROLLUP(stadt, land)
erzeugt Zwischensummen nach Stadt.
Soll nach Land zusammengefasst werden, ist erforderlich:
ROLLUP(land, stadt)
Künstliche NULL-Werte werden mit echten NULL-Werten verwechselt
Diese Prüfung ist nicht ausreichend:
CASE
WHEN land IS NULL
THEN 'Alle Länder'
END
Ein tatsächlich fehlendes Land würde ebenfalls als Gesamtsumme beschriftet.
Richtig ist:
CASE
WHEN GROUPING(land) = 1
THEN 'Alle Länder'
WHEN land IS NULL
THEN 'Land unbekannt'
ELSE land
END
Ein vollständiger CUBE erzeugt unnötige Kombinationen
Bei n Gruppierungsspalten kann ein vollständiger CUBE bis zu 2^n Gruppierungskombinationen erzeugen.
| Spalten | Kombinationen |
| 2 | 4 |
| 3 | 8 |
| 4 | 16 |
| 5 | 32 |
| 6 | 64 |
Ein CUBE über zahlreiche Spalten kann deshalb sehr große Ergebnismengen erzeugen.
Werden nur ausgewählte Aggregationen benötigt, ist GROUPING SETS meist präziser.
Nicht aggregierte Spalten fehlen in GROUP BY
Diese Abfrage ist ungültig:
SELECT
land,
stadt,
produkt,
SUM(betrag)
FROM umsatz_daten
GROUP BY ROLLUP(land, stadt);
produkt wird weder aggregiert noch gruppiert.
Oracle meldet in solchen Fällen typischerweise:
ORA-00979: not a GROUP BY expression
Entweder muss produkt in die Gruppierung aufgenommen oder aus der Auswahlliste entfernt werden.
Filter werden an der falschen Stelle angewendet
Eine Bedingung für Ausgangsdatensätze gehört in WHERE.
Eine Bedingung für berechnete Summen gehört in HAVING.
Falsch wäre beispielsweise:
WHERE SUM(betrag) > 1000
Aggregatfunktionen können nicht auf diese Weise in der WHERE-Klausel verwendet werden.
NVL wird vor GROUPING eingesetzt
Eine vorschnelle Ersetzung wie:
NVL(land, 'Alle Länder')
unterscheidet nicht zwischen einem gespeicherten NULL und einer Gesamtsumme.
Zuerst muss GROUPING ausgewertet werden:
CASE
WHEN GROUPING(land) = 1
THEN 'Alle Länder'
ELSE NVL(land, 'Land unbekannt')
END
Performancehinweise
ROLLUP, CUBE und GROUPING SETS sollten fachlich gezielt verwendet werden.
Ausgangsdaten früh einschränken
Selektive Bedingungen gehören in die WHERE-Klausel:
WHERE buchungsdatum >= :von
AND buchungsdatum < :bis
Dadurch muss Oracle nur den relevanten Zeitraum aggregieren.
Unnötige CUBE-Dimensionen vermeiden
Ein vollständiger CUBE über viele Spalten erzeugt zahlreiche Gruppierungskombinationen.
Statt:
GROUP BY CUBE(
jahr,
monat,
land,
stadt,
produkt,
vertriebskanal
)
sollten nur fachlich benötigte Gruppierungen mit GROUPING SETS angegeben werden.
Spalten mit sehr hoher Kardinalität prüfen
Eine Gruppierung nach eindeutigen oder nahezu eindeutigen Werten erzeugt kaum Verdichtung.
Beispiele:
Kundennummer
Auftragsnummer
Zeitstempel
Transaktions-ID
Solche Spalten sollten nur aufgenommen werden, wenn die Detailaggregation tatsächlich benötigt wird.
Ausführungsplan kontrollieren
Bei großen Tabellen sollte der Ausführungsplan geprüft werden:
EXPLAIN PLAN FOR
SELECT
land,
produkt,
SUM(betrag)
FROM umsatz_daten
GROUP BY CUBE(land, produkt);
Anschließend:
SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY);
Die tatsächliche Laufzeit hängt unter anderem von Datenmenge, Filtern, Partitionierung, verfügbarer Speichermenge und der Anzahl erzeugter Gruppierungen ab.
Entscheidungshilfe
ROLLUP verwenden, wenn
- die Daten eine natürliche Hierarchie besitzen,
- Zwischensummen von der Detailstufe bis zur Gesamtsumme benötigt werden,
- beispielsweise Jahr, Monat und Tag ausgewertet werden,
- Land, Region und Stadt hierarchisch zusammengehören.
CUBE verwenden, wenn
- alle Kombinationen mehrerer Dimensionen benötigt werden,
- Länder und Produkte unabhängig voneinander ausgewertet werden,
- neben Detailwerten auch Summen je Dimension benötigt werden,
- eine mehrdimensionale Analyse erstellt wird.
GROUPING SETS verwenden, wenn
- nur bestimmte Aggregationsebenen benötigt werden,
- ein vollständiger
CUBEunnötige Ergebnisse erzeugen würde, - mehrere
UNION ALL-Abfragen ersetzt werden sollen, - die Struktur des Berichts ausdrücklich festgelegt werden soll.
GROUPING verwenden, wenn
- echte
NULL-Werte von Summenzeilen unterschieden werden müssen, - Zwischensummen verständlich beschriftet werden sollen,
- einzelne Gruppierungsspalten geprüft werden.
GROUPING_ID verwenden, wenn
- mehrere Gruppierungsspalten vorhanden sind,
- Aggregationsebenen gefiltert werden sollen,
- Detail-, Zwischen- und Gesamtsummen sortiert werden,
- mehrere
GROUPING-Aufrufe vermieden werden sollen.
Häufige Fragen
Was ist der wichtigste Unterschied zwischen ROLLUP und CUBE?
ROLLUP bildet eine Hierarchie von links nach rechts und erzeugt entsprechende Zwischensummen.
CUBE berechnet alle möglichen Kombinationen der angegebenen Dimensionen.
Erzeugt ROLLUP immer eine Gesamtsumme?
Ein vollständiges:
ROLLUP(land, stadt)
erzeugt eine Gesamtsumme.
Bei einem partiellen ROLLUP:
GROUP BY land, ROLLUP(stadt)
bleibt land jedoch in jeder Gruppierung enthalten. Eine landübergreifende Gesamtsumme entsteht dann nicht.
Ist NULL in einer ROLLUP-Abfrage immer eine Summenzeile?
Nein. Die zugrunde liegenden Daten können echte NULL-Werte enthalten.
Nur GROUPING(spalte) = 1 weist sicher auf eine durch die Aggregation erzeugte Summenmarkierung hin.
Kann ich nur die Gesamtsumme ausgeben?
Ja. Bei zwei Gruppierungsspalten kann die Gesamtsumme beispielsweise so gefiltert werden:
HAVING GROUPING_ID(land, produkt) = 3
Kann GROUPING SETS eine UNION-ALL-Abfrage ersetzen?
In vielen Berichten ja. Mehrere Aggregationsebenen können innerhalb einer einzigen GROUP BY-Klausel definiert werden. Dadurch bleibt die Abfrage kompakter und einheitlicher.
Spielt die Reihenfolge bei CUBE eine Rolle?
Die Menge der erzeugten Gruppierungskombinationen bleibt bei denselben Spalten gleich. Die Reihenfolge beeinflusst jedoch die Bitpositionen und damit die Werte von GROUPING_ID.
Bei ROLLUP beeinflusst die Reihenfolge zusätzlich die fachliche Hierarchie der Zwischensummen.
Fazit
ROLLUP, CUBE und GROUPING SETS erweitern normale Oracle-SQL-Aggregationen um Zwischen- und Gesamtsummen.
Die passende Auswahl hängt vom gewünschten Bericht ab:
Hierarchische Zwischensummen:
ROLLUP
Alle Dimensionskombinationen:
CUBE
Gezielt ausgewählte Gruppierungen:
GROUPING SETS
Erkennung künstlicher Summenwerte:
GROUPING
Kennzeichnung und Filterung ganzer Aggregationsebenen:
GROUPING_ID
Für einfache hierarchische Berichte ist ROLLUP meist die passende Lösung. Bei unabhängigen Auswertungsdimensionen kann CUBE sinnvoll sein. Werden nur bestimmte Summenebenen benötigt, verhindert GROUPING SETS unnötige Kombinationen und beschreibt die gewünschte Berichtsstruktur besonders präzise.