HAVING
So wie eine 'WHERE'-Klausel die Zeilen in einem Datensatz auf diejenigen beschränkt, die die Suchbedingung erfüllen, so erlegt die 'HAVING'-Unterklausel Beschränkungen für die aggregierten Zeilen in einer gruppierten Menge auf.HAVING
ist optional und kann nur in Verbindung mit GROUP BY
verwendet werden.
Die Bedingung(en) in der HAVING
-Klausel können sich beziehen auf:
-
Jede aggregierte Spalte in der Auswahlliste.Dies ist der am häufigsten verwendete Fall.
-
Jeder aggregierte Ausdruck, der nicht in der Auswahlliste enthalten ist, aber im Kontext der Abfrage zulässig ist.Dies ist manchmal auch nützlich.
-
Jede Spalte in der
GROUP BY
-Liste.Obwohl es legal ist, ist es effizienter, diese nicht aggregierten Daten zu einem früheren Zeitpunkt zu filtern: in der WHERE-Klausel. -
Jeder Ausdruck, dessen Wert nicht vom Inhalt des Datasets abhängt (wie eine Konstante oder eine Kontextvariable).Dies ist gültig, aber völlig sinnlos, da es entweder die gesamte Menge unterdrückt oder unberührt lässt, basierend auf Bedingungen, die nichts mit der Menge selbst zu tun haben.
Eine HAVING
-Klausel kann nicht enthalten:
-
Nicht aggregierte Spaltenausdrücke, die nicht in der
GROUP BY
-Liste enthalten sind. -
Spaltenpositionen.Eine ganze Zahl in der
HAVING
-Klausel ist nur eine ganze Zahl. -
Spaltenaliase – nicht einmal, wenn sie in der
GROUP BY
-Klausel vorkommen!
Beispiele
Aufbauend auf unseren früheren Beispielen könnte dies verwendet werden, um kleine Schülergruppen zu überspringen:
select class,
count(*) as num_boys,
avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having count(*) >= 5;
So wählen Sie nur Gruppen mit einer Mindestaltersspanne aus:
select class,
count(*) as num_boys,
avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having max(age) - min(age) > 1.2;
Beachten Sie, dass Sie, wenn Sie wirklich an diesen Informationen interessiert sind, normalerweise min(age)
und max(age)
einschließen würden – oder den Ausdruck „`max(age) - min(age)
`" – auch in der Auswahlliste!
Um nur 3. Klassen einzubeziehen:
select class,
count(*) as num_boys,
avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having class starting with '3';
Besser wäre es, diese Bedingung in die WHERE-Klausel zu verschieben:
select class,
count(*) as num_boys,
avg(age) as boys_avg_age
from students
where sex = 'M' and class starting with '3'
group by class;