SQL GROUP BY und Aggregatfunktionen: Daten gruppieren und auswerten
Mit GROUP BY und Aggregatfunktionen wie COUNT, SUM und AVG verwandelst du rohe Datensätze in aussagekräftige Auswertungen. So funktioniert es Schritt für Schritt.
Du kannst mit SELECT schon Daten abfragen, filtern und sortieren. Aber irgendwann kommt der Punkt, an dem du keine einzelnen Zeilen mehr sehen willst, sondern Zusammenfassungen: Wie viele Bestellungen gab es pro Kunde? Was ist der durchschnittliche Preis pro Kategorie? Genau dafür gibt es GROUP BY und die Aggregatfunktionen. In diesem Beitrag lernst du, wie du aus rohen Datensätzen aussagekräftige Auswertungen machst.
Was sind Aggregatfunktionen?
Eine Aggregatfunktion nimmt viele Werte entgegen und gibt einen einzigen zurück. Statt jede Zeile einzeln anzuzeigen, verdichtet sie eine ganze Spalte zu einem Ergebnis. Die fünf wichtigsten sind:
COUNT()— zählt ZeilenSUM()— summiert ZahlenwerteAVG()— berechnet den DurchschnittMIN()— findet den kleinsten WertMAX()— findet den größten Wert
Ohne GROUP BY arbeiten sie über die gesamte Tabelle. Stell dir eine Tabelle bestellungen mit den Spalten id, kunde_id, betrag und kategorie vor:
SELECT COUNT(*) AS anzahl,
SUM(betrag) AS gesamt,
AVG(betrag) AS durchschnitt
FROM bestellungen;Das Ergebnis ist genau eine Zeile: die Gesamtzahl aller Bestellungen, die Summe aller Beträge und der Durchschnittsbetrag. Praktisch, aber oft willst du es feiner aufgeschlüsselt.
Gruppieren mit GROUP BY
Mit GROUP BY teilst du die Zeilen in Gruppen auf, und die Aggregatfunktion wird pro Gruppe berechnet. Willst du wissen, wie viel jeder Kunde insgesamt ausgegeben hat, gruppierst du nach kunde_id:
SELECT kunde_id,
COUNT(*) AS anzahl_bestellungen,
SUM(betrag) AS umsatz
FROM bestellungen
GROUP BY kunde_id;Jetzt bekommst du pro Kunde eine Zeile. Die Faustregel lautet: Jede Spalte in der SELECT-Liste muss entweder in der GROUP-BY-Klausel stehen oder in einer Aggregatfunktion verwendet werden. Würdest du hier zusätzlich betrag ohne Aggregat auswählen, wüsste die Datenbank nicht, welchen der vielen Beträge einer Gruppe sie zeigen soll — die meisten Systeme werfen dann einen Fehler.
Nach mehreren Spalten gruppieren
Du kannst auch nach mehreren Spalten gleichzeitig gruppieren. Dann entsteht für jede Kombination der Werte eine eigene Gruppe. Beispiel: Umsatz je Kunde und Kategorie:
SELECT kunde_id,
kategorie,
SUM(betrag) AS umsatz
FROM bestellungen
GROUP BY kunde_id, kategorie
ORDER BY kunde_id, umsatz DESC;Hier siehst du auch, dass sich GROUP BY und ORDER BY gut ergänzen: Zuerst wird gruppiert und aggregiert, danach das Ergebnis sortiert. So bekommst du pro Kunde die umsatzstärkste Kategorie zuerst.
Gruppen filtern mit HAVING
Ein häufiger Stolperstein: Mit WHERE kannst du keine Aggregatergebnisse filtern. WHERE wird ausgeführt, bevor gruppiert wird — dort gibt es die Aggregatwerte also noch gar nicht. Für Bedingungen auf Aggregaten gibt es HAVING, das nach dem Gruppieren greift:
SELECT kunde_id,
SUM(betrag) AS umsatz
FROM bestellungen
WHERE kategorie = 'Elektronik' -- filtert Zeilen VOR dem Gruppieren
GROUP BY kunde_id
HAVING SUM(betrag) > 500 -- filtert Gruppen NACH dem Aggregieren
ORDER BY umsatz DESC;Merke dir die Reihenfolge der Ausführung: erst WHERE (einzelne Zeilen), dann GROUP BY (Gruppen bilden), dann HAVING (Gruppen filtern), zum Schluss ORDER BY. Wenn du diese Abfolge im Kopf hast, weißt du immer, welche Klausel du brauchst.
COUNT im Detail: Zeilen, Werte und Eindeutiges
COUNT hat ein paar Feinheiten, die oft für Verwirrung sorgen. COUNT(*) zählt alle Zeilen einer Gruppe, egal ob Werte fehlen. COUNT(spalte) zählt nur Zeilen, in denen die Spalte nicht NULL ist. Und mit DISTINCT zählst du nur unterschiedliche Werte:
SELECT kategorie,
COUNT(*) AS zeilen,
COUNT(betrag) AS mit_betrag,
COUNT(DISTINCT kunde_id) AS aktive_kunden
FROM bestellungen
GROUP BY kategorie;Die Spalte aktive_kunden sagt dir, wie viele verschiedene Kunden in einer Kategorie bestellt haben — ein Kunde mit zehn Bestellungen zählt dabei nur einmal. Solche Unterscheidungen machen den Unterschied zwischen einer richtigen und einer irreführenden Auswertung aus.
Fazit
GROUP BY zusammen mit Aggregatfunktionen ist das Werkzeug, mit dem du aus vielen einzelnen Datensätzen verwertbare Kennzahlen ziehst. Wichtig ist, dass du die Rollen sauber trennst: WHERE filtert Zeilen vor dem Gruppieren, HAVING filtert Gruppen danach, und jede nicht-aggregierte Spalte gehört in die GROUP-BY-Klausel. Wenn du diese Regeln verinnerlichst, kannst du praktisch jede Reporting-Frage in eine saubere Abfrage übersetzen. Probier es am besten direkt an einer eigenen Tabelle aus — Umsatz pro Monat, Bestellungen pro Kunde oder Durchschnittsbewertung pro Produkt sind gute erste Übungen.