Gruppen filtern mit HAVING
Am Ende der letzten Lektion stand ein unbefriedigendes Ergebnis: Die bestbewertete Band hatte nur wenige Stimmen. Man möchte solche Gruppen aussortieren – aber WHERE hilft dabei nicht.
Warum WHERE nicht reicht
Überlege, bevor du es ausprobierst: Was würde diese Abfrage bedeuten?
SELECT b.name, AVG(w.punkte)
FROM bewertung AS w
JOIN auftritt AS a ON a.auftritt_id = w.auftritt_id
JOIN band AS b ON b.band_id = a.band_id
WHERE COUNT(*) >= 20
GROUP BY b.name;
Auflösung
Nichts Sinnvolles. WHERE entscheidet über einzelne Zeilen, und zwar bevor die Gruppen überhaupt gebildet werden. Zu diesem Zeitpunkt gibt es noch keine Gruppe, deren Größe man zählen könnte.
Die Bedingung „mindestens 20 Bewertungen" ist eine Aussage über eine fertige Gruppe. Dafür gibt es HAVING.
HAVING
HAVING filtert Gruppen, so wie WHERE Zeilen filtert.
| wirkt auf | Zeitpunkt | darf Aggregatfunktionen enthalten | |
|---|---|---|---|
WHERE |
einzelne Zeilen | vor dem Gruppieren | nein |
HAVING |
Gruppen | nach dem Gruppieren | ja |
Beides zusammen
Oft braucht man beide – und sie tun verschiedene Dinge:
a) Lies die Abfrage laut vor und übersetze jeden Teil in einen deutschen Satz.
b) Was passiert, wenn du WHERE a.dauer_min >= 60 entfernst? Warum ändern sich die Zahlen in beiden Spalten?
c) Was passiert, wenn du stattdessen HAVING COUNT(*) >= 2 entfernst?
Ein häufiger Fehler
Diese beiden Abfragen sehen ähnlich aus und liefern Verschiedenes:
-- A: alle Auftritte, danach nur Bands mit mindestens zwei davon
SELECT b.name, COUNT(*) FROM auftritt a JOIN band b ON b.band_id = a.band_id
GROUP BY b.name HAVING COUNT(*) >= 2;
-- B: nur die Auftritte auf der Hauptbühne, danach dieselbe Bedingung
SELECT b.name, COUNT(*) FROM auftritt a JOIN band b ON b.band_id = a.band_id
WHERE a.buehne_id = 1
GROUP BY b.name HAVING COUNT(*) >= 2;
B zählt nur die Auftritte auf der Hauptbühne. Eine Band mit einem Auftritt auf der Hauptbühne und drei anderswo taucht in A auf, in B nicht.
Wenn eine Auswertung merkwürdige Zahlen liefert, ist die Frage fast immer: Was steht im WHERE, und was gehört eigentlich ins HAVING?
Aufgaben
a) Alle Herkunftsländer, aus denen mehr als eine Band kommt, mit Anzahl.
b) Alle Bands, die mindestens dreimal aufgetreten sind, mit Anzahl der Auftritte.
c) Alle Genres mit mindestens vier Bands, mit Anzahl.
d) Alle Bühnen, auf denen insgesamt mehr als 20 000 Zuschauer waren – mit Bühnenname und Zuschauersumme.
Tipp 1: Zeile oder Gruppe?
Frage dich bei jeder Bedingung: Kann ich sie an einer einzelnen Zeile prüfen? Dann WHERE. Brauche ich dafür die ganze Gruppe? Dann HAVING.
Tipp 2: zu d)
„Insgesamt mehr als 20 000" ist eine Summe über die Gruppe. Also HAVING SUM(...) > 20000.