HAVING
Comme la clause WHERE
, la clause HAVING
restreint les lignes du jeu de données à celles qui satisfont la condition de recherche, à la différence que la clause HAVING
impose des restrictions sur les lignes agrégées du jeu groupé.La clause HAVING
est facultative et ne peut être utilisée qu’en conjonction avec la clause GROUP BY
.
La (les) condition(s) dans la clause 'HAVING' peuvent se référer à :
-
Toute colonne agrégée dans la liste de sélection
SELECT
. C’est le cas le plus couramment utilisé ; -
Toute expression agrégée qui ne figure pas dans la liste de sélection
SELECT
, mais qui est autorisée dans le contexte de la requête. C’est parfois utile ; -
Toute colonne de la liste
GROUP BY
. Cependant, il est plus efficace de filtrer les données non agrégées plus tôt dans la clauseWHERE
; -
Toute expression dont la valeur est indépendante du contenu de l’ensemble de données (telle qu’une constante ou une variable contextuelle). Cela est acceptable, mais n’a aucun sens, car une telle clause, qui n’a rien à voir avec l’ensemble de données lui-même, va soit supprimer l’ensemble entier, soit le laisser intact.
Une clause HAVING
ne peut pas contenir :
-
Expressions de colonnes non agrégées qui ne sont pas dans la liste GROUP BY ;
-
Position de la colonne. Un nombre entier dans une clause
HAVING
est simplement un nombre entier ; -
Les alias de colonnes — même s’ils apparaissent dans une clause
GROUP BY
.
Exemples
Reconstruire nos premiers exemples. Nous pouvons utiliser la clause "HAVING" pour exclure de petits groupes d’élèves :
SELECT
class,
COUNT(*) AS num_boys,
AVG(age) AS boys_avg_age
FROM students
WHERE sex = 'M'
GROUP BY class
HAVING COUNT(*) >= 5
Ne choisissez que les groupes dont l’écart d’âge minimum est de 1,2 an :
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
Notez que si vous êtes vraiment intéressé par cette information, c’est une bonne idée d’inclure min(age)
et max(age)
ou l’expression max(age) - min(age)
dans la liste de sélection.
La requête suivante ne sélectionne que les élèves de 3ème année :
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'
Cependant, il est bien mieux de déplacer cette condition dans la clause WHERE
:
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