SQL GROUP BY und Aggregatfunktionen: Fasse deine Daten zusammen

Published: 2026-04-08

GROUP BY fasst mehrere Zeilen, die in einer oder mehreren Spalten denselben Wert haben, zu einer einzigen Zusammenfassungszeile zusammen. In Kombination mit Aggregatfunktionen wie COUNT, SUM, AVG, MIN und MAX bildet es die Grundlage fast jeder Reporting- und Analyseabfrage. GROUP BY wird in allen SQL-Datenbanken unterstützt, darunter SQLite, PostgreSQL, MySQL, SQL Server und Oracle.

Beispieldaten

Wir verwenden in allen Beispielen zwei Tabellen:

employees-Tabelle:

id name department hire_date salary
1 Alice Engineering 2023-01-15 95000
2 Bob Engineering 2023-06-01 85000
3 Carol Engineering 2024-03-10 85000
4 Dave Sales 2023-02-20 72000
5 Eve Sales 2023-09-05 68000
6 Frank Sales 2024-01-15 65000
7 Grace Marketing 2023-04-01 82000
8 Henry Marketing 2024-06-01 70000

orders-Tabelle:

id customer product category quantity unit_price order_date status
1 Acme Corp Laptop Pro Electronics 3 1299.99 2026-01-05 delivered
2 Acme Corp Wireless Mouse Electronics 10 29.99 2026-01-12 delivered
3 Globex Office Chair Furniture 5 249.99 2026-01-18 delivered
4 Globex Standing Desk Furniture 2 599.99 2026-01-20 shipped
5 Initech Notebook Pack Stationery 20 12.99 2026-02-03 delivered
6 Initech Pen Set Stationery 15 8.99 2026-02-07 delivered
7 Acme Corp Monitor 27" Electronics 4 399.99 2026-02-14 delivered
8 Umbrella Ltd Laptop Pro Electronics 2 1299.99 2026-02-20 cancelled
9 Umbrella Ltd Desk Lamp Furniture 8 39.99 2026-03-01 delivered
10 Globex Wireless Mouse Electronics 12 29.99 2026-03-05 shipped
11 Initech Monitor 27" Electronics 1 399.99 2026-03-10 delivered
12 Acme Corp Standing Desk Furniture 1 599.99 2026-03-15 processing
Datensatz in DbGate Lite erkunden

GROUP BY-Syntax

SELECT column1, aggregate_function(column2)
FROM table_name
WHERE condition
GROUP BY column1
HAVING aggregate_condition
ORDER BY column1;
  • GROUP BY — eine oder mehrere Spalten, deren unterschiedliche Wertekombinationen jede Gruppe definieren
  • Aggregatfunktionen — berechnen einen einzelnen Wert aus allen Zeilen der Gruppe
  • HAVING — filtert Gruppen (ähnlich wie WHERE, aber für gruppierte Ergebnisse)
  • Jede Spalte in SELECT, die nicht in einer Aggregatfunktion steht, muss in GROUP BY erscheinen

Ausführungsreihenfolge von SQL

SQL-Klauseln werden in einer Reihenfolge geschrieben, aber in einer anderen Reihenfolge ausgeführt. Das erklärt, warum HAVING auf Aggregatfunktionen zugreifen kann, WHERE aber nicht, und warum du einen SELECT-Alias nicht in einer HAVING-Klausel verwenden kannst.

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
Schritt Klausel Was passiert
1 FROM Lädt die Tabelle(n) und wertet alle JOINs aus
2 WHERE Filtert einzelne Zeilen — Aggregatfunktionen sind hier nicht erlaubt
3 GROUP BY Fasst die verbleibenden Zeilen zu Gruppen zusammen
4 HAVING Filtert Gruppen — Aggregatfunktionen sind hier erlaubt
5 SELECT Berechnet Ausgabespalten und Aliasse
6 ORDER BY Sortiert das endgültige Ergebnisset

Darum läuft WHERE status = 'delivered' vor dem Gruppieren (schneller, zeilenweiser Filter), während HAVING COUNT(*) > 2 nach dem Gruppieren ausgeführt wird (filtert ganze Gruppen).

COUNT()

COUNT(*) zählt alle Zeilen in einer Gruppe. COUNT(column) zählt Nicht-NULL-Werte in dieser Spalte.

Beispiel: Anzahl der Mitarbeitenden pro Abteilung

Beispiel: Anzahl der Bestellungen pro Kunde

Beispiel: Gelieferte vs. andere Status zählen

Zähle nur Bestellungen, die einer Bedingung entsprechen, mit COUNT und einem CASE-Ausdruck:

SUM()

SUM(column) addiert alle Werte in der Gruppe für eine numerische Spalte.

Beispiel: Gesamtsalär pro Abteilung

Beispiel: Gesamtumsatz pro Kategorie

Berechne den Umsatz als quantity * unit_price:

Beispiel: Umsatz nach Kunde und Kategorie

Gruppiere nach mehreren Spalten, um den Umsatz weiter aufzuschlüsseln:

AVG()

AVG(column) gibt den arithmetischen Mittelwert aller Nicht-NULL-Werte in der Gruppe zurück.

Beispiel: Durchschnittsgehalt pro Abteilung

Beispiel: Durchschnittlicher Bestellwert pro Kunde

MIN() und MAX()

MIN(column) und MAX(column) geben den kleinsten bzw. größten Wert in der Gruppe zurück.

Beispiel: Gehaltsspanne pro Abteilung

Beispiel: Erstes und letztes Bestelldatum pro Kunde

Mehrere Aggregate kombinieren

Du kannst beliebig viele Aggregatfunktionen in einer einzigen Abfrage kombinieren.

Beispiel: Vollständige Abteilungsübersicht

Beispiel: Bestellübersicht pro Kunde

HAVING

HAVING filtert Gruppen nach der Aggregation — es ist das Äquivalent zu WHERE für gruppierte Ergebnisse.

Beispiel: Abteilungen mit mehr als zwei Mitarbeitenden

Beispiel: Kunden mit Gesamtumsatz über 2000

Beispiel: Kategorien mit durchschnittlichem Bestellwert unter 500

WHERE vs. HAVING

WHERE filtert einzelne Zeilen vor dem Gruppieren. HAVING filtert Gruppen nach der Aggregation.

Beispiel: Umsatz nur aus gelieferten Bestellungen pro Kunde

Verwende WHERE, um Zeilen vor dem Gruppieren auszuschließen, und dann HAVING, um Ergebnisse zu filtern:

GROUP BY mit JOINs

Du kannst Daten gruppieren, die sich über mehrere Tabellen erstrecken, indem du sie zuerst verbindest (JOIN).

Beispiel: Umsatz pro Abteilung über Join mit Employees

Beispiel: Bestellanzahl und Umsatz pro Kategorie und Monat

GROUP BY mit Ausdrücken

Du kannst nach berechneten Ausdrücken gruppieren, nicht nur nach einfachen Spalten.

Beispiel: Mitarbeitendeinstellungen pro Jahr

Beispiel: Bestellungen pro Monat

COUNT(DISTINCT)

COUNT(DISTINCT column) zählt die Anzahl der eindeutigen Werte in der Gruppe.

Beispiel: Eindeutige Produkte pro Kunde

Gruppen mit mehreren Bedingungen filtern

HAVING unterstützt jeden booleschen Ausdruck, einschließlich AND/OR-Kombinationen.

Beispiel: Wertvolle aktive Kunden

Finde Kunden mit mehr als einer Bestellung und einem Gesamtumsatz über 1000:

Praxisbeispiel: Verkaufsbericht

Kombiniere alles zu einem vollständigen Verkaufsübersichtsbericht.

Beispiel: Leistungsbericht nach Kategorie

Beispiel: Top-Produkt nach Umsatz

GROUP BY vs. Window-Funktionen

GROUP BY fasst Zeilen zu einer Zeile pro Gruppe zusammen. Window-Funktionen behalten alle Zeilen bei und fügen eine berechnete Spalte hinzu — Details findest du im SQL-Tutorial zu Window-Funktionen.

Beispiel: GROUP BY gibt eine Zeile pro Abteilung zurück

Beispiel: Window-Funktion behält alle Zeilen

Häufige Anwendungsfälle für GROUP BY

  • Reporting-Dashboards — Summiere Gesamtwerte, Durchschnitte und Anzahlen nach Kategorie oder Zeitraum
  • Headcount-Analyse — Zähle Mitarbeitende, Nutzer oder Datensätze nach Gruppe
  • Umsatzaufschlüsselung — Gesamt- und Durchschnittsumsatz nach Produkt, Region oder Kunde
  • Trendanalyse — Gruppiere nach Monat oder Jahr, um Muster im Zeitverlauf zu erkennen
  • Top-N pro Gruppe — Kombiniere mit Subqueries oder CTEs, um die besten Performer in jeder Gruppe zu finden
  • Datenvalidierung — Zähle Duplikate oder NULL-Werte über Gruppen hinweg
  • Kohortenanalyse — Gruppiere Nutzer nach Anmeldedatum oder Verhaltenssegment

Performance-Tipps

  1. GROUP-BY-Spalten indexieren — Indizes auf gruppierten Spalten beschleunigen den Sortier- und Gruppierungsschritt
  2. Früh mit WHERE filtern — Zeilen vor dem Gruppieren mit WHERE zu reduzieren ist schneller, als sie danach mit HAVING zu filtern
  3. SELECT * vermeiden — Wähle nur die Spalten, die du wirklich brauchst; Aggregatoperationen profitieren von schmaleren Daten
  4. Covering-Indizes verwenden — Ein Index, der sowohl die GROUP-BY-Spalte als auch die aggregierte Spalte enthält, kann einen vollständigen Tabellenscan vermeiden
  5. Materialisierte Views in Betracht ziehen — Für häufig berechnete Aggregate auf großen Tabellen unterstützen einige Datenbanken vorkalkulierte Zusammenfassungen

Zusammenfassung

  • GROUP BY fasst Zeilen, die dieselben Spaltenwerte haben, zu einer Zusammenfassungszeile pro eindeutiger Kombination zusammen
  • COUNT(*) zählt alle Zeilen; COUNT(column) zählt Nicht-NULL-Werte; COUNT(DISTINCT column) zählt eindeutige Werte
  • SUM summiert numerische Werte; AVG berechnet den Mittelwert; MIN / MAX finden die Grenzwerte
  • Jede SELECT-Spalte muss entweder in GROUP BY erscheinen oder in eine Aggregatfunktion eingeschlossen sein
  • WHERE filtert Zeilen vor dem Gruppieren; HAVING filtert Gruppen nach der Aggregation
  • Du kannst nach Ausdrücken gruppieren (z. B. SUBSTR(date, 1, 7) für Gruppierung auf Monatsebene)
  • Durch das Joinen von Tabellen vor dem Gruppieren kannst du Daten aus mehreren Quellen in einem Bericht kombinieren
  • Verwende Window-Funktionen statt GROUP BY, wenn du Kennzahlen auf Gruppenebene brauchst, ohne einzelne Zeilen zu verlieren

Probiere aus, GROUP BY mit JOINs, CASE-Ausdrücken und HAVING-Klauseln zu kombinieren, um genau die Berichte zu erstellen, die deine Datenanalyse benötigt!