Lektionen des Moduls (4/4)
Filtern von Gruppen: HAVING
Sobald Sie ein Ergebnis pro Gruppe haben (vorherige Lektion), möchten Sie es oft tun
Nur die Gruppen behalten, die eine Bedingung erfüllen: Abteilungen mit mehr
als 2 Personen, Projekte mit einem durchschnittlichen Budget über 100.000, Benutzer mit
mindestens 10 Bestellungen. Dazu reicht WHERE nicht aus.
Warum WO nicht ausreicht
WHERE filtert die Tabellenzeilen, vor der Aggregation. Es kann also nichts sehen
das Ergebnis von COUNT(*) oder AVG(...): bis WHERE ausgeführt wird, jene
Werte wurden noch nicht berechnet.
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM employees
WHERE COUNT(*) > 2 -- ❌ doesn't work
GROUP BY department_id;Um nach der Aggregation zu filtern, gibt es eine spezielle Klausel: HAVING.
Die Syntax
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column
HAVING condition_on_aggregate;-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 2;HAVING ist für GROUP BY das, was WHERE für FROM ist: die gleiche Idee
(„Filter“), aber nach der Gruppierung auf das Aggregat angewendet.
Die logische Reihenfolge der Klauseln
Um WHERE und HAVING nie wieder zu verwechseln, merken Sie sich die Reihenfolge
SQL führt sie mental aus:
FROM/JOIN– erstellt die Starttabelle durch Zusammenführen von Quellen.WHERE– löscht die Zeilen, die Sie nicht interessieren.GROUP BY– sammelt die verbleibenden Zeilen in Gruppen.HAVING– löscht die Gruppen, die Sie nicht interessieren.SELECT– berechnet die endgültigen Spalten (einschließlich Aggregate).ORDER BY/LIMIT– neu anordnen und ausschneiden.
Wichtige Hinweise:
- in
WHEREkönnen Sie nur Tabellenspalten verwenden; - In
HAVINGkönnen Sie Gruppierungsspalten und Aggregate verwenden.
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
WHERE e.hired_on >= '2018-01-01' -- filter rows
GROUP BY d.name
HAVING AVG(e.salary) > 35000 -- filter groups
ORDER BY average DESC;Probieren Sie es aus
Zeigen Sie für jede Abteilung den Namen (departments.name) und die Mitarbeiterzahl an, ABER nur für Abteilungen mit mindestens 2 Mitarbeitern. Zwei Spalten, eine Zeile pro qualifizierender Abteilung.
Hinweis anzeigen
Die Bedingung „mindestens 2“ wird in HAVING zu COUNT(*) >= 2.
Lösung nach 3 Versuchen verfügbar
Wiederholungsübung
Zeigen Sie die Abteilungen (departments.name) an, deren Durchschnittsgehalt 35.000 übersteigt. Berücksichtigen Sie nur Mitarbeiter, die ab 2018 eingestellt wurden. Zwei Spalten: Name und Durchschnitt. Sortierung nach Durchschnitt absteigend.
Hinweis anzeigen
WHERE filtert die Zeilen (ab 2018 eingestellte Mitarbeiter), HAVING filtert die Gruppen (Durchschnitt > 35000).
Lösung nach 3 Versuchen verfügbar