Lektion 4: Gruppierung mit GROUP BY |
In der Gruppe fühl ich mich wohl - Gruppeneinteilung mit group by |
Mit der group by-Klausel kannst Du Datensätze in Gruppen
einteilen. Dabei wird jeder Datensatz genau einer Gruppe zugeordnet. Im Bild stellt die Gesamtwolke die Menge aller Datensätze dar. Jeder Punkt symbolisiert einen Datensatz. Diese Menge ist mittels group by farbe in fünf Gruppen eingeteilt, z. B. haben wir links unten die Gruppe der "grünen" Datensätze. Hat man die Datensätze mittels group by in Gruppen eingeteilt, so kann man nur noch Angaben über die Gruppen machen, nicht mehr über einzelne Datensätze. Man kann also Informationen über die Gruppe der gelben Datensätze ausgeben, aber keine Detailangabe über den großen gelben Datensatz. |
Einführendes Beispiel |
Wir können die Datensätze der cia-Datenbank nach den Regionen gruppieren und dann die
Regionen ausgeben.
select Region from cia group by Region |
Ergebnis |
Typisches Beispiel |
Das obige Beispiel ist untypisch, weil man das Ergebnis einfacher auch so erhält: select distinct Region from cia
Der Mehrwert der group by-Klausel ergibt sich daraus, dass man mit den Aggregatfunktionen statistische Auswertungen der Gruppen vornehmen kann. Wir wollen die Einwohnerzahl der Regionen und deren durchschnittliches Bruttosozialprodukt ausgeben: select Region, sum(Einwohner), avg(BIP) from cia group by Region |
Ergebnis |
Tipp: Um die Ergebnistabelle nach den Einwohnerzahlen zu sortieren, ergänzen wir einfach order by 2, geben also die Nummer der Spalte an, nach der sortiert werden soll. |
Typischer Fehler |
Der typische Fehler im
Zusammenhang mit der Gruppierung besteht darin, dass nach der
Gruppenbildung noch versucht wird, Informationen von einzelnen Datensätzen
auszugeben. Zum Beispiel:
select Region, Name, sum(Einwohner), AVG(BIP) from cia group by Region Man kann zwar für jede Gruppe die Region und die Summe der Einwohner angeben, aber nicht den Namen, denn der ist für jedes Land einer Region anders. |
Ergebnis |
Die meisten Datenbanksysteme weisen diese select-Anweisung mit einer Fehlermeldung zurück. Sinngemäß heißt
es meist, dass das Attribut Name nicht Bestandteil der group by-Klausel ist. MySQL bildet eine Ausnahme,
akzeptiert die select-Anweisung und liefert folgendes Ergebnis:
|
Interpretation |
Dass das vom Datenbanksystem MySQL gelieferte Ergebnis tatsächlich fragwürdig ist, zeigt sich gleich beim ersten Datensatz. Für die Region
Afrika wird als Name Algerien angegeben. Hier wird also zur Gruppe Afrika das Einzeldatum Name ausgegeben. (vgl. im
Eingangsbild den großen gelben Datensatz).
Wir halten also fest, dass bei einer select-Anweisung mit group by in der select-Klausel nur die Gruppierungsattribute und die Aggregatfunktionen vorkommen dürfen. |
Gruppenwahl - die HAVING-Klausel |
Wenn man nicht an allen
Gruppen interessiert ist, so kann man mit der having-Klausel die in Frage
kommenden Gruppen auswählen. Bildlich bedeutet das, dass man einige der
entstandenen Gruppen von der weiteren Betrachtung ausschließt.
Aber nach welchen Kriterien kann man Gruppen auswählen? Das geht nur mit einer Gruppeneigenschaft, also entweder danach wie die Gruppen gebildet wurden oder mit einer Aggregatfunktion, die eine Gruppeneigenschaft bestimmt. Deshalb wird in einer having-Klausel in aller Regel eine Aggregatfunktion benutzt, während in einer where-Klausel keine Aggregatfunktion möglich ist. |
Beispiel |
Es sollen die Regionen angezeigt werden, die mehr als 100 Millionen Einwohner haben.
select Region, sum(Einwohner) from cia group by Region having sum(Einwohner) > 1E08 |
Ergebnis |
WHERE und GROUP BY |
Auch eine select-Anweisung mit group by-Klausel kann eine where-Bedingung enthalten. Die where-Bedingung
wählt aus der gesamten Datenmenge die Datensätze aus, die anschließend gruppiert werden.
Im Bild hat die where-Bedingung die farbigen Datensätze ausgewählt, das anschließende group by hat die farbigen Datensätze nach der Farbe gruppiert. |
Ein Beispiel |
Es sollen die Einwohnerzahlen der Regionen angezeigt werden, wobei nur Länder mit mehr als 100 Millionen Einwohner berücksichtigt werden sollen.
select Region, sum(Einwohner) from cia where Einwohner > 1E08 group by Region |
Ergebnis |
Erläuterung |
Um das Zustandskommen der Werte besser verstehen zu können, wandeln wir die select-Anweisung so ab,
dass wir die Einwohnerzahlen der beteiligten Länder ausgeben. Dazu ergänzen wir in der
group by-Klausel und in der select-Klausel das Attribut Name. Die Gruppierung wird
dann über die Kombination der Attribute Region und Name durchgeführt.
In der Region Nordamerika gibt es die zwei Länder Mexiko und die Vereinigte Staaten von Amerika mit mehr als 100 Millionen Einwohner. Die Summe ihrer Einwohnerzahlen wurde in der vorherigen Abfrage ermittelt. |
Und jetzt alles zusammen! - WHERE, GROUP BY und HAVING |
Kommen in einer Abfrage where, group by und having vor, so wird in dieser Reihenfolge das
Ergebnis bestimmt. Zuerst werden die zu betrachtenden Datensätze mittels where selektiert,
dann werden diese mit group by gruppiert und zum Schluss werden mit having die gewünschten Gruppen ausgewählt.
Die where-Klausel wählt also die farbigen Datensätze aus, die group by-Klausel gruppiert nach Farben und die having-Klausel wählt die rote, grüne und gelbe Gruppe aus. |
Ein Beispiel |
Wir gruppieren wieder die Länder mit mehr als 100 Millionen Einwohner, nehmen davon aber
nur die Regionen mit mehr als 250 Millionen Einwohnern.
select Region, sum(Einwohner) from cia where Einwohner > 1E08 group by Region having sum(Einwohner) > 250000000 |
Ergebnis |
Zusammenfassung |
Die select-Anweisung hat folgende grammatische Struktur, wobei optionale Anteile in [Klammern] gesetzt sind
und der senkrechte Strich in geschweiften {Klammern} Alternativen beschreibt.
SELECT [DISTINCT] select_ausdruck, ... [FROM Tabellen] [WHERE where-Bedingung] [GROUP BY {positive_ganzzahl | spalten_name} [ASC | DESC], ...]] [HAVING where-Bedingung] [ORDER BY {positive_ganzzahl | spalten_name} [ASC | DESC], ...] [LIMIT [offset,] zeilen] SQL wertet diese Klauseln in der Reihenfolge FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT aus. Dabei funktionieren die Klauseln im Sinne einer Pipeline, das heißt die Ausgabe einer Klausel ist die Eingabe für die nächste. In funktionaler Notation wird die Reihenfolge der Auswertung wie folgt dargestellt: LIMIT(ORDER BY(SELECT(HAVING(GROUP BY(WHERE(FROM...)))))) |
Hier geht es weiter... |
Genug der grauen Theorie - jetzt wird es wieder praktisch. Hier geht es zu den Übungen der Lektion 4. |