Zum Inhalt springen

7. Aggregation und Gruppierung

Zu Zen-Modus wechseln

Während das Abrufen einzelner Zeilen wesentlich ist, liegt die wahre Stärke von SQL in seiner Fähigkeit, Rohdaten in aussagekräftige Erkenntnisse zu verwandeln. Im professionellen Umfeld müssen Sie selten jede einzelne Transaktion oder jeden Schülerdatensatz sehen; stattdessen brauchen Sie Antworten auf übergeordnete Fragen:

  • Was ist die Durchschnittsnote in einer Klasse?
  • Wie viele Schüler sind in jedem Fach angemeldet?
  • Wie hoch war der Gesamtumsatz im letzten Monat?

Hier kommen Aggregatfunktionen und die GROUP BY-Klausel ins Spiel. Aggregation erlaubt es Ihnen, mehrere Datenzeilen zu einem einzigen Zusammenfassungswert “zusammenzufalten”, während die Gruppierung es ermöglicht, Ihre Daten in logische Behälter (Buckets) zu unterteilen, bevor diese Berechnungen durchgeführt werden. Die Beherrschung dieser Werkzeuge macht aus einem Datenbankbenutzer einen Datenanalysten und erlaubt es Ihnen, Muster und Trends in Ihren relationalen Daten zu erkennen.

Die GROUP BY-Klausel wird verwendet, um identische Daten in Gruppen anzuordnen. Dieses “Zusammenfalten” von Zeilen ist die Voraussetzung dafür, Berechnungen auf bestimmten Teilmengen Ihrer Daten durchzuführen (z. B. die Durchschnittsnote pro Klasse zu berechnen statt für die gesamte Schule).

Stellen Sie sich Ihre Tabelle students vor. Wenn Sie nach der Spalte class gruppieren, erstellt SQL einen “Bucket” für jeden eindeutigen Klassennamen (4A, 4B usw.). Jede Zeile, die zu “4A” gehört, wird in den 4A-Bucket gelegt.

Die goldene Regel der Gruppierung:

Bei Verwendung von GROUP BY muss jede in Ihrer SELECT-Anweisung aufgeführte Spalte eine von zwei Bedingungen erfüllen:

  1. Sie ist in der GROUP BY-Klausel enthalten.
  2. Sie ist in eine Aggregatfunktion eingeschlossen (wie SUM oder COUNT).
SELECT class, COUNT(student_id)
FROM students
GROUP BY class;

Die folgende Abfrage ist nicht gültig, weil first_name weder gruppiert noch aggregiert ist. Die Datenbank wüsste nicht, welchen first_name sie für die gesamte Klasse anzeigen soll, da es in jeder Klasse mehrere Schüler gibt.

SELECT class, first_name
FROM students
GROUP BY class;

Bisher haben wir nach einer einzelnen Spalte gruppiert. Sie können auch mehrere Spalten in der GROUP BY-Klausel auflisten. Entscheidend ist zu verstehen, was zu einem Bucket wird: SQL erstellt einen Bucket für jede eindeutige Kombination von Werten über alle aufgeführten Spalten hinweg - nicht einen Bucket pro Spalte.

Denken Sie an die Kisten zurück. Bei GROUP BY class war die Beschriftung auf jeder Kiste nur der Klassenname. Bei GROUP BY class, subject wird die Beschriftung auf jeder Kiste zu einem Paar: (class, subject). Zwei Zeilen landen nur dann in derselben Kiste, wenn sie in beiden Werten übereinstimmen.

Stellen Sie sich eine Tabelle grades wie diese vor:

subjectscore
Databases1
Databases1
Databases2
Networking1
Networking3
Networking3

Nun zählen wir, wie oft jede Note pro Fach vergeben wurde:

SELECT subject, score, COUNT(*) AS how_many
FROM grades
GROUP BY subject, score;

SQL bildet einen Bucket pro eindeutiger (subject, score)-Kombination und zählt die Zeilen in jedem:

subjectscorehow_many
Databases12
Databases21
Networking11
Networking32

Was Sie beachten sollten:

  • “Databases” für sich allein ist kein Bucket mehr. (Databases, 1) und (Databases, 2) sind zwei getrennte Buckets, weil die zweite Gruppierungsspalte sie auseinandertrennt.
  • Je mehr Spalten Sie zu GROUP BY hinzufügen, desto mehr Buckets erhalten Sie - und desto kleiner wird jeder Bucket (feinere Granularität).
  • Die Reihenfolge der Spalten in GROUP BY ändert nicht, welche Buckets gebildet werden: GROUP BY subject, score und GROUP BY score, subject erzeugen dieselben Gruppen. (Sie ist nur für die angezeigte Reihenfolge relevant, wenn Sie ein ORDER BY hinzufügen.)
  • Die goldene Regel gilt weiterhin: Jede Spalte in der SELECT-Liste (subject und score) ist entweder in GROUP BY aufgeführt oder in eine Aggregatfunktion eingeschlossen.

Aggregatfunktionen führen eine Berechnung auf einer Menge von Werten durch und geben einen einzigen Wert zurück. Sie werden fast immer zusammen mit GROUP BY verwendet.

FunktionBeschreibungBeispiel
COUNT()Gibt die Anzahl der Zeilen zurück.COUNT(*) zählt alle Zeilen; COUNT(col) zählt Nicht-NULL-Werte.
SUM()Berechnet die Gesamtsumme einer numerischen Spalte.SUM(score)
AVG()Berechnet das arithmetische Mittel (Durchschnitt).AVG(score)
MIN()Findet den kleinsten Wert in einer Menge.MIN(birth_date) (Der älteste Schüler)
MAX()Findet den größten Wert in einer Menge.MAX(birth_date) (Der jüngste Schüler)

Beispiel - Analyse der Klassenleistung:

SELECT
subject,
AVG(score) AS average_grade,
COUNT(*) AS total_exams
FROM grades
GROUP BY subject;

Einer der häufigsten Verwirrungspunkte ist die Frage, wann WHERE und wann HAVING zu verwenden ist. Beide dienen dem Filtern, aber sie wirken in unterschiedlichen Phasen der Abfrage.

Die WHERE-Klausel filtert einzelne Zeilen bevor irgendeine Gruppierung stattfindet. Wenn eine Zeile die WHERE-Bedingung nicht erfüllt, gelangt sie gar nicht erst in einen “Bucket”.

Die HAVING-Klausel filtert Gruppen nachdem die GROUP BY- und Aggregatberechnungen durchgeführt wurden. Sie verwenden HAVING, wenn Sie anhand eines Aggregatergebnisses filtern möchten (z. B. “zeige nur Klassen mit mehr als 20 Schülern”).

Vergleichsbeispiel:

Im folgenden Beispiel filtert WHERE vor der Gruppierung Schüler heraus, die vor 2010 geboren wurden, während HAVING nach der Gruppierung Gruppen (Klassen) herausfiltert, die 2 oder weniger Schüler haben.

SELECT class, COUNT(*) as student_count
FROM students
WHERE birth_date > '2010-01-01'
GROUP BY class
HAVING COUNT(*) > 2;

Um zu verstehen, warum HAVING nach GROUP BY kommt, hilft ein Blick auf die Reihenfolge, in der die Datenbank Ihren Befehl tatsächlich verarbeitet. Auch wenn wir SELECT zuerst schreiben, führt die Datenbank es erst viel später aus:

  1. FROM & JOIN: Die Datenbank sammelt alle Rohdaten.
  2. WHERE: Einzelne Zeilen werden herausgefiltert.
  3. GROUP BY: Die verbleibenden Zeilen werden in Buckets organisiert.
  4. HAVING: Ganze Buckets (Gruppen) werden anhand von Aggregatwerten herausgefiltert.
  5. SELECT: Die endgültigen Spalten und Berechnungen werden für die Anzeige vorbereitet.
  6. ORDER BY: Die endgültige Ergebnismenge wird sortiert.

In relationalen Datenbanken erfordert die Datenanalyse oft den Wechsel von der Betrachtung einzelner Datensätze hin zur Erzeugung übergeordneter Zusammenfassungen. Dieses Kapitel hat behandelt, wie man Aggregatfunktionen verwendet, um Berechnungen durchzuführen, und die GROUP BY-Klausel, um Daten in logische Teilmengen zu organisieren.

Gruppierung erlaubt es Ihnen, mehrere Zeilen auf Basis gemeinsamer Werte in bestimmten Spalten zu einzelnen Zusammenfassungszeilen “zusammenzufalten”.

  • Die Bucket-Logik: Wenn Sie nach einer Spalte gruppieren, legt SQL alle Datensätze mit demselben Wert in einen einzigen “Bucket” zur Berechnung.
  • Die goldene Regel: Jede Spalte in Ihrer SELECT-Liste muss entweder Teil der GROUP BY-Klausel sein oder in eine Aggregatfunktion eingeschlossen sein. Das stellt sicher, dass keine Mehrdeutigkeit darüber besteht, welcher Datenpunkt für eine Gruppe angezeigt werden soll.

Diese Funktionen führen Berechnungen auf einer Menge von Werten innerhalb einer Gruppe (oder der gesamten Tabelle) durch, um einen einzigen informativen Wert zurückzugeben.

FunktionZweckHäufiger Anwendungsfall
COUNT()Zählt die Anzahl der Elemente.Schüler pro Klasse oder Gesamtzahl der Bestellungen zählen.
SUM()Addiert numerische Werte.Gesamtumsatz oder Gesamtpunkte berechnen.
AVG()Findet das arithmetische Mittel.Durchschnittliche Testergebnisse oder Preise bestimmen.
MIN()Findet den niedrigsten Wert.Die niedrigste Note oder das früheste Datum identifizieren.
MAX()Findet den höchsten Wert.Die beste Punktzahl oder den neuesten Eintrag identifizieren.

Das Verständnis des Zeitpunkts dieser beiden Klauseln ist entscheidend für eine korrekte Datenanalyse.

  • WHERE (Vorfilter): Wirkt auf einzelne Zeilen vor der Gruppierung. Verwenden Sie es, um bestimmte Daten von der Berechnung gänzlich auszuschließen (z. B. “Inaktive Benutzer ausschließen”).
  • HAVING (Nachfilter): Wirkt auf Gruppen nach der Aggregation. Verwenden Sie es, um anhand der Ergebnisse von Funktionen wie SUM oder COUNT zu filtern (z. B. “Nur Abteilungen mit mehr als 10 Mitarbeitern anzeigen”).

Um erfolgreiche komplexe Abfragen zu schreiben, müssen Sie sich merken, dass die Datenbank die Klauseln nicht in der Reihenfolge verarbeitet, in der sie geschrieben werden. Der Ausführungsablauf ist:

  1. FROM / JOIN (Daten sammeln)
  2. WHERE (Zeilen filtern)
  3. GROUP BY (in Buckets organisieren)
  4. HAVING (Buckets filtern)
  5. SELECT (Ergebnisse berechnen)
  6. ORDER BY (endgültige Liste sortieren)

  • Berechnen: Funktionen wie SUM, AVG und COUNT verwenden, um Kennzahlen aus Rohdaten zu gewinnen.
  • Organisieren: GROUP BY anwenden, um Berichte zu erzeugen, die nach bestimmten Attributen kategorisiert sind (z. B. nach Datum, Kategorie oder Abteilung).
  • Unterscheiden: Korrekt zwischen WHERE und HAVING wählen, je nachdem, ob der Filter auf Rohzeilen oder aggregierte Ergebnisse zutrifft.
  • Analysieren: Die Gültigkeit einer Abfrage anhand der “goldenen Regel” der Gruppierung bestimmen.
  • Reihenfolge beachten: Komplexe SQL-Anweisungen entsprechend der logischen Ausführungsreihenfolge strukturieren, um Syntax- und Logikfehler zu vermeiden.