SQL Quest
Se connecter English 0 XP Niv. 1
Intermédiaire

SQL HAVING : filtrer les groupes

4 min de lecture · 3 exemples exécutables · mis à jour le 9 octobre 2026

Après un GROUP BY, on veut parfois ne garder que certains groupes : les villes de plus de 10 clients, les catégories dont le prix moyen dépasse 20 €, les clients qui ont passé au moins 5 commandes. WHERE ne peut pas faire ce travail, car il agit avant le regroupement. Il faut HAVING.

Syntaxe

SELECT colonne, FONCTION(colonne)
FROM table
WHERE condition_sur_les_lignes
GROUP BY colonne
HAVING condition_sur_les_groupes;

Comment ça marche

WHEREHAVING
Agit surles lignesles groupes
Momentavant le GROUP BYaprès le GROUP BY
Peut contenir COUNT, SUM…nonoui

On peut utiliser les deux dans la même requête : WHERE retire d'abord des lignes, GROUP BY forme les groupes avec celles qui restent, puis HAVING retire des groupes.

Quand une condition porte sur une colonne simple (et non sur une agrégation), mettez-la plutôt dans le WHERE : la base travaille alors sur moins de lignes.

Schéma

groupes
villeCOUNT(*)
Lyon5
Paris2
Nantes3
résultat
villeCOUNT(*)
Lyon5
Nantes3
HAVING COUNT(*) >= 3 : après le regroupement, seuls les groupes d'au moins 3 lignes sont gardés.

Schéma simplifié pour illustrer le principe. Les exemples ci-dessous utilisent la vraie base d'exercices de SQL Quest (une boutique en ligne fictive : voir le schéma complet).

Exemples avec leurs résultats

1. Garder les grands groupes

Les villes qui comptent plus de 10 clients.

SELECT ville, COUNT(*) AS nb_clients
FROM clients
GROUP BY ville
HAVING COUNT(*) > 10;
Essayer dans le bac à sable
Résultat
villenb_clients
Bordeaux14
Lyon12
Paris13
Strasbourg11

4 lignes au total

2. Filtrer sur une moyenne

Les catégories dont le prix moyen dépasse 30 €.

SELECT categorie, ROUND(AVG(prix), 2) AS prix_moyen
FROM produits
GROUP BY categorie
HAVING AVG(prix) > 30;
Essayer dans le bac à sable
Résultat
categorieprix_moyen
Informatique146,43
Maison36,45

2 lignes au total

3. WHERE et HAVING ensemble

Parmi les commandes livrées seulement, les clients qui en ont au moins 6.

SELECT client_id, COUNT(*) AS livrees
FROM commandes
WHERE statut = 'livrée'
GROUP BY client_id
HAVING COUNT(*) >= 6
ORDER BY livrees DESC;
Essayer dans le bac à sable
Résultat
client_idlivrees
398
108
746

3 lignes au total

Les erreurs fréquentes

Mettre l'agrégation dans WHERE

SQLite répond misuse of aggregate : au moment du WHERE, les groupes n'existent pas encore.

À éviter
SELECT ville, COUNT(*) FROM clients WHERE COUNT(*) > 10 GROUP BY ville;
Correct
SELECT ville, COUNT(*) FROM clients GROUP BY ville HAVING COUNT(*) > 10;

Placer HAVING avant GROUP BY

HAVING vient toujours après GROUP BY dans l'écriture de la requête.

À éviter
SELECT ville, COUNT(*) FROM clients HAVING COUNT(*) > 10 GROUP BY ville;
Correct
SELECT ville, COUNT(*) FROM clients GROUP BY ville HAVING COUNT(*) > 10;

Utiliser HAVING pour une condition simple

Ça marche, mais c'est moins efficace : filtrez les lignes dès le WHERE.

À éviter
SELECT ville, COUNT(*) FROM clients GROUP BY ville HAVING ville <> 'Paris';
Correct
SELECT ville, COUNT(*) FROM clients WHERE ville <> 'Paris' GROUP BY ville;

Exercices

Essayez d'écrire la requête vous-même avant d'ouvrir la solution.

Défi 1. Affichez les départements dont le salaire moyen dépasse 4 000 €.

Voir une solution
SELECT departement, ROUND(AVG(salaire)) AS moyenne FROM employes GROUP BY departement HAVING AVG(salaire) > 4000;
departementmoyenne
Direction9 500
IT4 760
RH4 233
Ventes4 554

4 lignes au total

Essayer dans le bac à sable

Défi 2. Affichez les commandes (commande_id) qui contiennent au moins 4 lignes.

Voir une solution
SELECT commande_id, COUNT(*) AS nb_lignes FROM lignes_commande GROUP BY commande_id HAVING COUNT(*) >= 4 LIMIT 10;
commande_idnb_lignes
44
54
74
104
144
224
244
274

10 lignes au total · 8 affichées

Essayer dans le bac à sable
Envie de vous entraîner davantage ?

Les exercices interactifs sont corrigés automatiquement, avec un prof qui explique vos erreurs. Une leçon résumée reste affichée à côté de l'éditeur.

Faire les exercices interactifs

Questions fréquentes

Peut-on utiliser HAVING sans GROUP BY ?

Oui : la table entière forme alors un seul groupe. C'est rarement utile en pratique.

Peut-on utiliser un alias dans HAVING ?

SQLite et MySQL l'acceptent (HAVING nb_clients > 10). Pour du code portable, répétez l'expression : HAVING COUNT(*) > 10.

HAVING est-il plus lent que WHERE ?

Pour une même condition sur une colonne simple, oui, car HAVING s'applique après avoir regroupé toutes les lignes. Réservez HAVING aux conditions sur des agrégations.

À lire ensuite