Zurück zur Artikelliste Artikel
17 Leseminuten

GROUP BY und Aggregatfunktionen: Ein vollständiger Überblick

Die SQL-Funktionen GROUP BY und Aggregat sind für die Aggregation von Daten sowie für die Analyse von Daten und die Erstellung von Berichten unerlässlich. Lassen Sie uns diese Funktionen gemeinsam erkunden!

In SQL sind GROUP BY und Aggregatfunktionen eine der beliebtesten Funktionen der Sprache. Die Datenaggregation ist für die Datenanalyse und die Erstellung von Berichten von entscheidender Bedeutung; um alle Daten in einem Datensatz sinnvoll nutzen zu können, müssen sie oft aggregiert werden.

Aber was ist Datenaggregation? Einfach ausgedrückt: Sie gruppieren Daten auf der Grundlage gemeinsamer Werte und führen für jede Datengruppe eine Berechnung durch. Sie könnten zum Beispiel eine Liste von Hunden nach ihrer Rasse gruppieren und dann eine Berechnung durchführen, um die durchschnittliche Größe für jede Rasse zu ermitteln. Diese Aufgabe wird durch die GROUP BY-Klausel und die Aggregatfunktion AVG() ermöglicht.

Wenn Sie Ihr Wissen über GROUP BY auffrischen möchten, ist unser SQL für Anfänger Kurs ideal. Er enthält 129 interaktive Übungen, die Sie in etwa 10 Stunden absolvieren können. Er behandelt Themen wie das Filtern von Daten, die Verwendung logischer Operatoren, die Verknüpfung und die Verwendung von Mengenoperatoren.

Die Grundsyntax von GROUP BY mit Aggregaten

GROUP BY ist eine Klausel in SQL, die Daten mit gleichen Werten in Gruppen zusammenfasst. Die Gruppierung erfolgt nach Spalte(n), wobei alle Zeilen mit demselben Wert in dieser Spalte zu einer Gruppe gehören. Sie können dann für jede Gruppe zusammenfassende Berechnungen durchführen, z. B. Zählung, Summierung oder Mittelwertbildung von Werten. Mit GROUP BY können Sie zum Beispiel die Anzahl der Mitarbeiter in einer Abteilung, das Gesamtgehalt oder das Durchschnittsgehalt pro Abteilung usw. berechnen.

Die Syntax von GROUP BY mit einer Aggregatfunktion lautet:

SELECT column1, 
        column2, 
        ..., 
        aggregate_function(column_name)
FROM table_name
WHERE filtering_condition
GROUP BY column1, column2, …
HAVING filtering_condition;

Die Aggregatfunktion wird in die Anweisung SELECT geschrieben, und das Ergebnis der Funktion wird als zusätzliche Spalte angezeigt.

Die Klausel GROUP BY enthält die Spalten, nach denen Ihre Ausgabe gruppiert werden soll. Diese Klausel wird häufig zusammen mit den Klauseln WHERE und HAVING zur Filterung verwendet. In der Syntax steht WHERE vor GROUP BY, während HAVING danach kommt. (Ich werde später mehr über diese beiden Klauseln erklären.) Außerdem werden Ihre Daten manchmal NULLs enthalten, so dass es für Sie interessant sein wird zu erfahren , wie GROUP BY mit NULLs umgeht.

Ein Beispiel für GROUP BY in Aktion ist im folgenden GIF zu sehen.

Wie SQL GROUP BY funktioniert

In diesem einfachen Beispiel werden die Daten nach Regisseuren gruppiert und die Anzahl der Filme angezeigt, die jeder von ihnen gemacht hat.

SQL-Aggregatfunktionen

Die Aggregatfunktionen von SQL werden verwendet, wenn Sie Berechnungen mit Daten durchführen und einen einzigen Wert zurückgeben möchten.

Die gebräuchlichsten Aggregatfunktionen in SQL sind:

  • COUNT() - Zählt die Zeilen in der angegebenen Spalte.
  • SUM() - Gibt die Summe aller Werte zurück.
  • AVG() - Berechnet den Durchschnitt einer Gruppe von Werten.
  • MIN() - Gibt das Minimum (den niedrigsten Wert) der angegebenen Werte zurück.
  • MAX() - Gibt das Maximum (den höchsten Wert) der angegebenen Werte zurück.

In unseren Anleitungen erfahren Sie, wie Sie diese Funktionen verwenden, um Aggregate für die gesamte Tabelle zu berechnen:

Es ist wichtig zu beachten, dass die Funktion COUNT() mehrere verschiedene Verwendungsvarianten hat:

  • COUNT(*) Zählt alle Zeilen in einer Ergebnismenge, einschließlich NULL-Werte und Duplikate.
  • COUNT(expression) Zählt die Nicht-NULL-Werte in einer Ergebnismenge.
  • COUNT(DISTINCT) Zählt eindeutige Werte und ignoriert Duplikate.

Weitere Details finden Sie in unserem Leitfaden Was ist der Unterschied zwischen COUNT(*), COUNT(1), COUNT(column) und COUNT(DISTINCT)?

Verwendung von GROUP BY mit SQL-Aggregatfunktionen

Ich verwende die Tabelle albums um zu zeigen, wie Aggregatfunktionen und GROUP BY zusammenarbeiten. Das Skript zum Erstellen der Tabelle finden Sie hier.

Diese Tabelle enthält Daten über Musikalben. Hier ist ein Schnappschuss:

idartistalbumrelease_yearlengthlabel
1Grant GreenThe Latin Bit19630:38:56Blue Note Records
2AC/DCHigh Voltage19760:44:23Atlantic Records
3Brother Jack McDuffTo Seek a New Home19700:33:12Blue Note Records
4Grant GreenGreen Is Beautiful19700:37:33Blue Note Records
5Wayne ShorterMoto Grosso Feio19740:42:22Blue Note Records

Beispiel 1: COUNT() mit GROUP BY

Hier ist ein Beispielcode, der die Anzahl der Alben nach Label zählt:

SELECT label,
	 COUNT(*) AS number_of_albums
FROM albums
GROUP BY label; 

Ich wähle das Label aus und verwende COUNT(*), um die Anzahl der Alben zu ermitteln. Das Sternchen (*) ist eine Abkürzung für das Zählen aller Zeilen. Wenn ich die Ausgabe nach Label gruppiere, zeigt COUNT() die Anzahl der Alben pro Label an.

Hier ist die Ausgabe:

labelnumber_of_albums
Atlantic Records13
Blue Note Records12
Stax Records14

Weitere Lektüre:

Beispiel 2: SUMME() mit GROUP BY

Der folgende Code summiert die Albumlängen, um die gesamte verfügbare Musik pro Künstler anzuzeigen:

SELECT artist,
	 SUM(length) AS total_music_available
FROM albums
GROUP BY artist;

Die Funktion SUM() wird auf die Spalte length angewendet, und die Ausgabe wird dann nach dem Künstler gruppiert.

Dies ist das Ergebnis des Codes:

artisttotal_music_available
Isaac Hayes6:30:02
Otis Redding1:34:09
Brother Jack McDuff1:58:11
Aretha Franklin1:47:07
Grant Green3:10:11
John Prine1:21:57
Led Zeppelin3:32:07
Wayne Shorter2:38:02
Albert King3:08:28
AC/DC2:05:23

Weitere Lektüre:

Beispiel 3: AVG() mit GROUP BY

Dieser Code berechnet die durchschnittliche Albumlänge der einzelnen Künstler:

SELECT artist,
	 AVG(length) AS average_album_length
FROM albums
GROUP BY artist; 

Um das gewünschte Ergebnis zu erhalten, müssen Sie AVG() auf die Spalte length anwenden und die Ausgabe nach artist gruppieren.

So sieht die Ausgabe aus:

artistaverage_album_length
Isaac Hayes1:05:00
Otis Redding0:31:23
Brother Jack McDuff0:39:24
Aretha Franklin0:35:42
Grant Green0:38:02
John Prine0:40:59
Led Zeppelin0:42:25
Wayne Shorter0:39:31
Albert King0:37:42
AC/DC0:41:48

Weitere Lektüre:

Beispiel 4: MIN() und MAX() mit GROUP BY

Lassen Sie uns die kürzeste und die längste Albumlänge für jedes Jahr ermitteln:

SELECT release_year,
	 MIN(length) AS minimum_album_length,
	 MAX(length) AS maximum_album_length
FROM albums
GROUP BY release_year
ORDER BY release_year; 

Wie in früheren Beispielen werden die Aggregatfunktionen auf die Spalte length angewendet; MIN() für das kürzeste und MAX() für das längste Album.

Die Ausgabe ist nach Erscheinungsjahr gruppiert.

Ich habe außerdem die Klausel ORDER BY hinzugefügt, um die Ausgabe vom frühesten bis zum neuesten Jahr zu sortieren, damit sie besser lesbar ist.

Hier ist die Code-Ausgabe:

release_yearminimum_album_lengthmaximum_album_length
19620:34:490:34:49
19630:38:560:38:56
19640:30:170:30:17
19650:32:220:42:45
19670:32:510:41:08
19680:29:300:29:30
19690:31:300:46:00
19700:33:120:43:04
19710:42:371:33:38
19720:37:500:44:46
19730:40:571:43:10
19740:42:220:46:00
19760:39:590:44:23
19770:41:010:41:01

Weitere Lektüre:

Fortgeschrittene GROUP BY-Techniken

Im vorherigen Abschnitt wurden die Grundlagen der Verwendung von SQL-Aggregatfunktionen und GROUP BY behandelt. Mit diesen Grundlagen können wir nun einige fortgeschrittene GROUP BY Techniken untersuchen.

Aggregierte Ergebnisse mit HAVING filtern

Um aggregierte Ergebnisse zu filtern, müssen Sie die HAVING Klausel verwenden. Ihre Syntax ist hier dargestellt:

SELECT column1, 
       column2, 
       ..., 
       aggregate_function(column_name)
FROM table_name
GROUP BY column1, column2, …
HAVING filtering_condition;

HAVING HAVING vergleicht die aggregierten Werte mit der Filterbedingung und gibt nur die Werte zurück, die diese Bedingung erfüllen. Mehr dazu erfahren Sie in unserem Artikel über die HAVING-Klausel.

Ich möchte Ihnen ein Beispiel zeigen. Der folgende Code berechnet die durchschnittliche Albumlänge pro Künstler, zeigt aber nur diejenigen an, deren durchschnittliche Albumlänge unter 40 Minuten liegt.

SELECT artist,
	 AVG(length) AS average_album_length
FROM albums
GROUP BY artist
HAVING AVG(length) < '00:40:00';

Ich habe die Funktion AVG() verwendet, wie ich es zuvor getan habe. Die Klausel HAVING ist neu. Um die Daten auf die gewünschte Weise zu filtern, habe ich in HAVING die gleiche Durchschnittsberechnung wie in SELECT geschrieben. Dann verwende ich den Vergleichsoperator "kleiner als" (<), um jedes gruppierte Ergebnis mit einem Wert zu vergleichen (in diesem Fall 40 Minuten). Dieser Wert wird in einfache Anführungszeichen gesetzt (''). Der Wert in den Anführungszeichen muss im Format HH:MM:SS (Stunden:Minuten:Sekunden) geschrieben werden, da die Werte in der Spalte length vom Datentyp INTERVAL sind.

Hier ist die Ausgabe:

artistaverage_album_length
Otis Redding0:31:23
Brother Jack McDuff0:39:24
Aretha Franklin0:35:42
Grant Green0:38:02
Wayne Shorter0:39:31
Albert King0:37:42

Das Prinzip ist das gleiche, egal welche Aggregatfunktion Sie verwenden, aber hier sind die Kochbücher, die Ihnen mit einigen anderen Funktionen helfen:

Gruppieren nach mehreren Spalten

Bislang habe ich Daten nach einer Spalte gruppiert. Es ist jedoch auch möglich, nach zwei oder mehr Spalten zu gruppieren.

Das ist nicht kompliziert: Sie müssen nur alle Gruppierungsspalten in GROUP BY auflisten und sie durch Kommas trennen.

Auf diese Weise gruppieren Sie nicht nur nach den Spaltenwerten, sondern auch nach der Kombination von Werten in allen Gruppierungsspalten. Wenn Sie den Wert A in Spalte_1 und den Wert B in Spalte_2 haben, ist dies eine Gruppe. Gibt es z. B. in Spalte_1 den Wert A und in Spalte_2 den Wert C, so bildet dies eine weitere Gruppe - obwohl die Werte in Spalte_1 dieselben sind wie im vorherigen Beispiel.

Beispiel

Der folgende Code zeigt die Anzahl der Alben des Künstlers und das Jahr der Veröffentlichung an:

SELECT artist,
	 release_year,
	 COUNT(*) AS number_of_albums
FROM albums
GROUP BY artist, release_year
ORDER BY artist, release_year;

Ich verwende COUNT(*), um die Anzahl der Alben zu ermitteln. Die Ausgabe ist nach Künstler und Erscheinungsjahr gruppiert. Wie Sie sehen können, sind dies genau die Spalten in GROUP BY und sie sind durch ein Komma getrennt.

Um die Ausgabe besser lesbar zu machen, habe ich die Daten nach Künstler alphabetisch und vom frühesten bis zum spätesten Erscheinungsjahr sortiert.

Dies ist der Schnappschuss der Ausgabe:

artistrelease_yearnumber_of_albums
AC/DC19762
AC/DC19771
Albert King19621
Albert King19671
Albert King19691
Albert King19721
Albert King19741
Aretha Franklin19671
Aretha Franklin19681
Aretha Franklin19721
Brother Jack McDuff19692
Brother Jack McDuff19701

Zwei Aggregatfunktionen in einer Abfrage

Es ist auch möglich, eine Abfrage zu schreiben, die zwei Aggregatfunktionen enthält. Nein, es ist nicht so, wie Sie denken: Sie schreiben nicht eine Aggregatfunktion innerhalb einer anderen. Das ist in SQL nicht möglich.

Zwei Aggregatfunktionen in einer Abfrage können zwei Dinge bedeuten:

  1. Einfacher Ansatz: Verwendung von zwei Aggregatfunktionen in zwei Spalten der gleichen SELECT.
  2. Fortgeschrittener Ansatz: Verwendung des Ergebnisses einer Aggregatfunktion in einer anderen Aggregatfunktion.

Eine Abfrage, zwei Aggregatfunktionen: Der einfache Ansatz

Der einfache Ansatz besteht also darin, zwei Aggregatfunktionen in zwei verschiedenen Aggregatspalten in einer SELECT zu haben. Dabei kann es sich um dieselbe Funktion handeln, die auf verschiedene Spalten angewendet wird, um verschiedene Funktionen, die auf dieselbe Spalte angewendet werden, oder um verschiedene Funktionen, die auf verschiedene Spalten angewendet werden. Das spielt eigentlich keine Rolle; der Punkt ist, dass Sie zwei Aggregationen in einer Abfrage haben. Diese Aggregationen "kommunizieren" nicht, d.h. sie sind in keiner Weise voneinander abhängig.

Beispiel

In diesem Beispiel verwende ich die Tabelle package_deliveries mit dem hier verlinkten Skript.

Die Tabelle enthält Informationen über die Anzahl der Pakete, die täglich in mehrere Städte geliefert werden.

Hier sind die ersten sechs Zeilen der Tabelle:

iddate_of_deliverynumber_of_packagescity_of_deliverycountry_of_delivery
12024-03-0149KrakowPoland
22024-03-01528WarsawPoland
32024-03-01158GdanskPoland
42024-03-0128RijekaCroatia
52024-03-0197SplitCroatia
62024-03-0164ZagrebCroatia

Der folgende Code berechnet die Gesamtzahl und die durchschnittliche Anzahl der Pakete pro Stadt.

SELECT city_of_delivery,
	 SUM(number_of_packages) AS total_number_of_packages,
	 AVG(number_of_packages) AS average_number_of_packages
FROM package_deliveries
GROUP BY city_of_delivery;

Wie Sie sehen, hat die Abfrage zwei Aggregate: eines mit SUM() und eines mit AVG(). Es ist völlig egal, wie viele Aggregatfunktionen Sie in die Abfrage schreiben. Wichtig ist nur, dass jedes Aggregat als eigene Codezeile oder Ausgabespalte behandelt wird.

Hier ist das Ergebnis:

city_of_deliverytotal_number_of_packagesaverage_number_of_packages
Split531177.00
Izmir5,9361,978.67
Ankara9,1393,046.33
Gdansk712237.33
Rijeka627209.00
Zagreb930310.00
Istanbul13,8574,619.00
Krakow673224.33
Warsaw2,358786.00

Eine Abfrage, zwei Aggregatfunktionen: Der fortgeschrittene Ansatz

Die fortgeschrittene Version ist die, bei der die Aggregate "kommunizieren", d. h. Sie müssen zunächst einen aggregierten Wert finden und diesen dann zur Berechnung eines anderen aggregierten Wertes verwenden. Dies wird in der Regel entweder durch Unterabfragen oder Common Table Expressions (CTEs) erreicht.

Ich zeige Ihnen die Verwendung von Unterabfragen in dem folgenden Beispiel. Unser Leitfaden zur Kombination zweier Aggregatfunktionen in GROUP BY deckt beide Ansätze ab.

Beispiel

Der folgende Code gibt die durchschnittliche tägliche Anzahl von Paketen zurück, die in jedem Land zugestellt wurden:

SELECT country_of_delivery,
	 AVG(pd.daily_number_of_packages) AS average_daily_number_of_packages
FROM (SELECT date_of_delivery, 
	       country_of_delivery,
	 	 SUM(number_of_packages) AS daily_number_of_packages
	FROM package_deliveries
	GROUP BY date_of_delivery, country_of_delivery) AS pd
GROUP BY country_of_delivery;

Zunächst muss die Anzahl der täglich in jedem Land zugestellten Pakete ermittelt werden, was die erste Aggregation darstellt. Die zweite Aggregation verwendet dieses Ergebnis und berechnet den Tagesdurchschnitt pro Land.

Die erste Aggregation ist in der Subquery enthalten. Sie verwendet die Funktion SUM() und listet die Spalten date_of_delivery und country_of_delivery in SELECT auf. Die Ausgabe wird nach denselben Spalten gruppiert.

Jetzt kann ich die Hauptabfrage schreiben, wobei ich in AVG() auf die Spalte daily_number_of_packages aus der Unterabfrage verweise. Ich gruppiere die Ausgabe nach Land und erhalte die durchschnittliche tägliche Anzahl der zugestellten Pakete für jedes Land.

country_of_deliveryaverage_daily_number_of_packages
Turkey9,644.00
Croatia696.00
Poland1,247.67

GROUP BY mit bedingten Aggregaten

Die Anweisung CASE oder CASE WHEN kennzeichnet Daten auf der Grundlage ihrer Werte. Diese Anweisung kann auch mit GROUP BY verwendet werden.

Die Gruppierung von Daten durch bedingte Aggregate bedeutet, dass Sie CASE WHEN mit GROUP BY verwenden. Allerdings - und das ist wichtig - muss das CASE WHEN, das Sie in SELECT schreiben, auch in GROUP BY erscheinen.

Beispiel

Anhand der Tabelle aus dem vorherigen Beispiel kann ich einen Code schreiben, der die Länder in EU- und Nicht-EU-Länder unterteilt und die Gesamtzahl der zugestellten Pakete für jede Kategorie anzeigt:

SELECT
  CASE 
   WHEN country_of_delivery = 'Turkey' THEN 'Non-EU'
   ELSE 'EU'
  END,
  SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY CASE 
   WHEN country_of_delivery = 'Turkey' THEN 'Non-EU'
   ELSE 'EU'
  END;

Die Anweisung CASE besagt, dass die Türkei als Nicht-EU-Land kategorisiert werden sollte. Diese Bedingung ist in WHEN aufgeführt. Die Kategorie für alle anderen Länder ist EU, die in ELSE angegeben ist.

Die Anweisung CASE beginnt mit CASE (daher der Name) und endet mit dem Schlüsselwort END.

Ich verwende die Funktion SUM(), um die Gesamtzahl der Pakete zu berechnen. Um diesen Wert nach Kategorie anzuzeigen, habe ich einfach die gesamte Anweisung CASE WHEN in GROUP BY kopiert.

Hier ist die Ausgabe:

casetotal_number_of_packages
Non-EU28,932
EU5,831

Wenn Sie weitere Beispiele benötigen, um dies vollständig zu verstehen, lesen Sie einen unserer Leitfäden:

GROUP BY-Erweiterungen: ROLLUP, CUBE, GRUPPIERUNGSSÄTZE

Die drei SQL GROUP BY Erweiterungen sind:

  • ROLLUP - Erzeugt eine Summenzeile für die in GROUP BY aufgeführten Gruppen.
  • CUBE - Erzeugt Zwischensummen für alle Kombinationen der Gruppen in GROUP BY.
  • GROUPING SETS - Aggregiert die Ausgabe auf mehreren Ebenen.

In diesem Beispiel zeige ich Ihnen, wie GROUPING SETS funktioniert. Wie die anderen beiden Erweiterungen funktionieren, erfahren Sie in unserem Handbuch zu den GROUP BY-Erweiterungen.

Beispiel

Der folgende Code gibt die Anzahl der zugestellten Pakete pro Land und pro Datum aus:

SELECT country_of_delivery,
	 date_of_delivery,
	 SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY GROUPING SETS(country_of_delivery, date_of_delivery)
ORDER BY country_of_delivery, date_of_delivery;

Ich beginne mit SUM(), um die Anzahl der Pakete zu berechnen.

In GROUP BY schreibe ich GROUPING SETS mit allen Aggregationsebenen innerhalb der Klammern.

Die Ausgabe zeigt die Anzahl der zugestellten Pakete nach Land und nach Zustellungsdatum:

country_of_deliverydate_of_deliverytotal_number_of_packages
CroatiaNULL2,088
PolandNULL3,743
TurkeyNULL28,932
NULL2024-03-012,730
NULL2024-03-0211,208
NULL2024-03-0320,825

Es kann hilfreich sein, sich die Gruppierungssätze als zwei separate Abfragen vorzustellen. Die erste Abfrage gruppiert nach Land ...

SELECT country_of_delivery,
       NULL AS date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery
ORDER BY country_of_delivery;

... und gibt die ersten drei Zeilen der vorherigen Ausgabe zurück:

country_of_deliverydate_of_deliverytotal_number_of_packages
CroatiaNULL2,088
PolandNULL3,743
TurkeyNULL28,932

Die zweite Abfrage gruppiert nach Lieferdatum ...

SELECT NULL AS country_of_delivery,
       date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY date_of_delivery
ORDER BY date_of_delivery;

... und gibt die anderen drei Zeilen des ursprünglichen Ergebnisses aus:

country_of_deliverydate_of_deliverytotal_number_of_packages
NULL2024-03-012,730
NULL2024-03-0211,208
NULL2024-03-0320,825

Mit anderen Worten, wenn Sie diese beiden separaten Gruppierungsabfragen mit UNION zusammenführen ...

SELECT country_of_delivery,
       NULL AS date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery

UNION 

SELECT NULL AS country_of_delivery,
       date_of_delivery,
       SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY date_of_delivery
ORDER BY country_of_delivery, date_of_delivery;

... erhalten Sie genau das gleiche Ergebnis wie mit GROUPING SETS.

country_of_deliverydate_of_deliverytotal_number_of_packages
CroatiaNULL2,088
PolandNULL3,743
TurkeyNULL28,932
NULL2024-03-012,730
NULL2024-03-0211,208
NULL2024-03-0320,825

Häufige Fehler bei der Verwendung von GROUP BY

Verwechslung von ORDER BY und GROUP BY

Dies liegt oft daran, dass man nicht weiß, was GROUP BY tut.

Lassen Sie es mich anhand eines Beispiels demonstrieren.

Nehmen wir an, Sie möchten die Gesamtzahl der Pakete nach dem Land der Zustellung ermitteln.

Wenn Sie mit GROUP BY nicht vertraut sind, könnten Sie eine naive Lösung mit ORDER BY schreiben.

SELECT date_of_delivery,
	 city_of_delivery,
	 country_of_delivery
FROM package_deliveries
ORDER BY country_of_delivery;

Nachdem Sie nun die Daten nach Land sortiert haben, wie im Schnappschuss unten gezeigt, beschließen Sie, die Werte manuell zu summieren, um das Ergebnis nach Land zu erhalten.

date_of_deliverycity_of_deliverycountry_of_delivery
2024-03-01RijekaCroatia
2024-03-01SplitCroatia
2024-03-01ZagrebCroatia
2024-03-02RijekaCroatia
2024-03-02SplitCroatia
2024-03-02ZagrebCroatia
2024-03-03ZagrebCroatia
2024-03-03SplitCroatia
2024-03-03RijekaCroatia
2024-03-01KrakowPoland
2024-03-01WarsawPoland

Aber warum sollten Sie etwas manuell tun, was GROUP BY automatisch tut? Anstatt die Daten nach Land zu sortieren, sollten Sie nach diesem Land gruppieren und SUM() verwenden, um die Daten zu summieren:

SELECT country_of_delivery,
	 SUM(number_of_packages) AS total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery
ORDER BY country_of_delivery;

Sie erhalten dann sofort die gewünschte Ausgabe:

country_of_deliverytotal_number_of_packages
Croatia2,088
Poland3,743
Turkey28,932

Lesen Sie mehr über die Unterschiede zwischen GROUP BY und ORDER BY und wie Sie GROUP BY und ORDER BY zusammen verwenden können.

WHERE und HAVING verwechseln

Ein weiterer häufiger Fehler ist der Versuch, aggregierte Werte mit WHERE zu filtern. Das ist nicht möglich - WHERE wird verwendet, um einzelne Zeilen vor der Aggregation zu filtern. Dagegen dient HAVING zum Filtern von Gruppen von Zeilen nach der Aggregation.

Beispiel

Wenn Sie die durchschnittliche Anzahl der täglich zugestellten Pakete nach Stadt ermitteln und nur die Pakete mit mehr als 500 Paketen anzeigen möchten, könnten Sie diese Abfrage schreiben:

SELECT city_of_delivery,
	 AVG(number_of_packages) AS average_number_of_packages
FROM package_deliveries
WHERE AVG(number_of_packages) > 500
GROUP BY city_of_delivery;

Sie wird einen Fehler zurückgeben, da WHERE keine Aggregatfunktion als Argument akzeptiert. (Das bedeutet nicht, dass Sie WHERE nie mit GROUP BY verwenden können; das können Sie, aber nicht, um Gruppen zu filtern.)

In diesem Fall sollten Sie HAVING verwenden:

SELECT city_of_delivery,
	 AVG(number_of_packages) AS average_number_of_packages
FROM package_deliveries
GROUP BY city_of_delivery
HAVING AVG(number_of_packages) > 500;

Es ist die gleiche Abfrage mit AVG() und GROUP BY. Der einzige Unterschied ist HAVING, wobei Sie die Berechnung AVG() mit 500 vergleichen.

In der Ausgabe werden nur Städte angezeigt, deren Tagesdurchschnitt über 500 liegt.

city_of_deliveryaverage_number_of_packages
Izmir1,978.67
Ankara3,046.33
Istanbul4,619.00
Warsaw786.00

Erfahren Sie mehr darüber im Artikel über HAVING vs. WHERE.

Auflistung nicht aggregierter Spalten in SELECT, aber nicht in WHERE

Die einfache Regel, die Sie sich merken sollten, ist, dass jede nicht aggregierte Spalte, die Sie in SELECT schreiben, auch in GROUP BY enthalten sein sollte. Wenn Sie das nicht tun, weiß die Datenbank nicht, welcher Wert angezeigt werden soll, wenn mehrere verschiedene Werte in derselben Gruppe sind.

Beispiel

Ein Beispiel: Sie schreiben eine Abfrage, die die Gesamtzahl der Pakete nach Land und Stadt berechnen soll.

SELECT country_of_delivery,
       city_of_delivery,
	 SUM(number_of_packages) total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery;

Sicher, Sie haben Land und Stadt in SELECT, aber Sie haben vergessen, die Stadt in GROUP BY einzutragen. Diese Abfrage wird nicht ausgeführt. Sie wird einen Fehler zurückgeben. Auch wenn die Meldungen in PostgreSQL, Oracle und anderen Datenbanken unterschiedlich formuliert sind, ist die Meldung dieselbe: Die Spalte city_of_delivery muss in GROUP BY erscheinen.

Selbst wenn der Befehl ausgeführt würde, wäre die Datenbank verwirrt. Sie würde etwa Folgendes denken: "Sie wollen Städte anzeigen, aber nicht nach Stadt gruppieren? Woher soll ich wissen, welche Stadt ich in der Ausgabe anzeigen soll, wenn jedes Land drei Städte hat? Bitte fügen Sie die Städte in GROUP BY ein, damit ich jede Stadt als eigene Gruppe anzeigen kann."

Sie helfen also, indem Sie die Stadt der Lieferung in GROUP BY aufnehmen:

SELECT country_of_delivery,
       city_of_delivery,
	 SUM(number_of_packages) total_number_of_packages
FROM package_deliveries
GROUP BY country_of_delivery, city_of_delivery;

Ja, es ist eine Gruppierung nach zwei Spalten, und Sie haben bereits gelernt, wie man das macht. Hier ist die Ausgabe der Abfrage:

country_of_deliverycity_of_deliverytotal_number_of_packages
CroatiaZagreb930
CroatiaRijeka627
CroatiaSplit531
TurkeyIstanbul13,857
PolandWarsaw2,358
PolandKrakow673
TurkeyAnkara9,139
PolandGdansk712
TurkeyIzmir5,936

Andere Fehler

Es gibt auch einige andere Fehler, wie z. B. das Vergessen von GROUP BY mit Aggregatfunktionen oder das Nicht-Gruppieren nach einem eindeutigen Schlüssel. Diese und einige weitere Fehler werden in diesem Artikel über häufige GROUP BY-Fehler behandelt.

Weitere SQL GROUP BY Ressourcen

Nachdem Sie diesen Überblick über die SQL GROUP BY Klausel gelesen haben, sollten Sie eine Vorstellung von ihrer Verwendung und ihren Herausforderungen haben. Wenn Sie jedoch GROUP BY beherrschen wollen, müssen Sie mehr ins Detail gehen.

Das tun Sie am besten, indem Sie sich einige unserer Kurse und Kochbücher ansehen. Hier sind einige meiner Vorschläge zum Weiterlernen:

  • Erstellen einfacher SQL-Berichte - Dieser Kurs für Fortgeschrittene konzentriert sich auf die Feinheiten der Verwendung von GROUP BY - Gruppierung nach mehreren Spalten, Verwendung von HAVING, Kombination von GROUP BY mit CASE WHEN, der Unterschied zwischen COUNT(*) und COUNT(id) usw.
  • SQL-Praxis - Die Kurse in diesem Bereich haben Abschnitte, die sich mit verschiedenen SQL-Themen befassen, darunter auch eine ganze Reihe von GROUP BY.

Und vergessen Sie nicht unsere Artikel mit den GROUP BY Beispielen. Zwei meiner Favoriten sind SQL-Praxis: 10 GROUP BY-Übungen mit detaillierten Lösungen und die 9 wichtigsten SQL GROUP BY-Interview-Fragen.

Darüber hinaus gibt es ein SQL for Data Analysis Cheat Sheet, das einen eigenen Abschnitt für GROUP BY enthält.

Viel Spaß beim Lernen!