
La clause HAVING en SQL Oracle : filtrer les groupes de données
La clause HAVING en SQL Oracle est un outil indispensable pour filtrer les résultats issus d’un regroupement de données. Contrairement à WHERE qui agit sur les lignes individuelles, HAVING s’applique après l’agrégation réalisée par GROUP BY. Elle permet aux développeurs et analystes de cibler précisément les groupes qui satisfont une condition métier, comme identifier les départements dépassant un budget ou les clients avec un panier moyen élevé.
Définition et cas d’usage de HAVING en SQL Oracle
La clause HAVING est utilisée conjointement avec GROUP BY pour poser une condition de filtrage sur un groupe agrégé. Elle intervient après le calcul des fonctions d’agrégation telles que SUM(), COUNT(), AVG(), MIN() ou MAX().
Différence fondamentale entre WHERE et HAVING
Il est crucial de comprendre la distinction entre ces deux clauses :
- WHERE filtre les lignes avant le regroupement.
- HAVING filtre les groupes après le regroupement et le calcul des agrégats.
Cas d’usage en entreprise
Dans un contexte professionnel, HAVING est couramment utilisé pour :
- Identifier les régions dont le chiffre d’affaires dépasse un seuil défini.
- Lister les produits commandés plus de N fois sur une période donnée.
- Détecter les employés ayant cumulé plus d’un certain nombre d’heures supplémentaires.
- Surveiller les comptes bancaires présentant plus de X transactions mensuelles.
Oracle Database, utilisé massivement dans les grandes entreprises, tire pleinement parti de cette clause dans les requêtes analytiques et les tableaux de bord décisionnels.
Syntaxe de la clause HAVING en SQL Oracle
Voici la syntaxe complète d’une requête utilisant HAVING dans Oracle :
SELECT colonne1, fonction_agregation(colonne2)
FROM nom_table
[WHERE condition_sur_lignes]
GROUP BY colonne1
HAVING condition_sur_agregat
[ORDER BY colonne1];Explication des paramètres essentiels
| Élément | Description |
|---|---|
SELECT | Colonnes et agrégats à afficher dans le résultat |
FROM | Table(s) source(s) des données |
WHERE | Filtre optionnel appliqué avant le regroupement |
GROUP BY | Colonnes servant de critère de regroupement |
HAVING | Condition portant sur un agrégat, appliquée après GROUP BY |
ORDER BY | Tri optionnel des résultats finaux |
Ordre d’exécution Oracle : FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Respecter cet ordre logique est essentiel pour écrire des requêtes performantes.
Exemples pratiques de HAVING en SQL Oracle
Exemple 1 — Départements dont la masse salariale dépasse 50 000 €
Contexte métier : Le service RH souhaite identifier les départements dont la masse salariale totale dépasse 50 000 € afin d’initier une revue budgétaire.
-- Sélection du département et du total des salaires
SELECT
d.nom_departement,
SUM(e.salaire) AS masse_salariale_totale
FROM
employes e
JOIN departements d ON e.id_departement = d.id_departement
-- Regroupement par département
GROUP BY
d.nom_departement
-- Filtre : on ne conserve que les départements dépassant 50 000 €
HAVING
SUM(e.salaire) > 50000
-- Tri décroissant pour faciliter la lecture
ORDER BY
masse_salariale_totale DESC;Résultat attendu : Une liste des départements triés par masse salariale décroissante, ne contenant que ceux dont le total dépasse le seuil défini. Oracle calcule d’abord les sommes par département, puis applique le filtre HAVING.
Exemple 2 — Clients ayant passé plus de 5 commandes en 2024
Contexte métier : L’équipe commerciale veut cibler les clients les plus actifs pour leur proposer un programme de fidélité.
-- Nombre de commandes par client sur l'année 2024
SELECT
c.id_client,
c.nom_client,
COUNT(o.id_commande) AS nb_commandes
FROM
clients c
JOIN commandes o ON c.id_client = o.id_client
-- Filtre sur l'année AVANT regroupement (rôle de WHERE)
WHERE
EXTRACT(YEAR FROM o.date_commande) = 2024
-- Regroupement par client
GROUP BY
c.id_client, c.nom_client
-- Filtre sur l'agrégat : clients avec plus de 5 commandes
HAVING
COUNT(o.id_commande) > 5
-- Tri par nombre de commandes décroissant
ORDER BY
nb_commandes DESC;Point Oracle : La fonction EXTRACT(YEAR FROM date) est native à Oracle et permet d’isoler l’année d’un champ de type DATE ou TIMESTAMP. Le WHERE réduit le volume de données traitées avant le GROUP BY, ce qui améliore les performances.
Erreurs courantes avec HAVING en SQL Oracle
Erreur fréquente : utiliser HAVING sans GROUP BY
Une erreur classique consiste à employer HAVING sans clause GROUP BY. Bien qu’Oracle tolère cette syntaxe dans certains cas (en considérant l’ensemble de la table comme un seul groupe), cela conduit souvent à des résultats inattendus ou à une requête non optimisée.
Code problématique :
-- INCORRECT : HAVING sans GROUP BY explicite
SELECT COUNT(id_commande) AS total_commandes
FROM commandes
HAVING COUNT(id_commande) > 100;Solution recommandée : Toujours associer HAVING à un GROUP BY explicite pour garantir la lisibilité et la maintenabilité du code.
-- CORRECT : avec GROUP BY explicite
SELECT
id_client,
COUNT(id_commande) AS total_commandes
FROM commandes
GROUP BY id_client
HAVING COUNT(id_commande) > 100;Erreur fréquente : confondre WHERE et HAVING pour les agrégats
Utiliser WHERE avec une fonction d’agrégation provoque une erreur Oracle ORA-00934 : group function is not allowed here.
-- INCORRECT : WHERE ne peut pas filtrer un agrégat
SELECT id_departement, AVG(salaire)
FROM employes
WHERE AVG(salaire) > 3000 -- ORA-00934
GROUP BY id_departement;-- CORRECT : utiliser HAVING pour filtrer sur un agrégat
SELECT id_departement, AVG(salaire) AS salaire_moyen
FROM employes
GROUP BY id_departement
HAVING AVG(salaire) > 3000;Résumé : ce qu’il faut retenir sur HAVING en SQL Oracle
| Point clé | Détail |
|---|---|
| Rôle de HAVING | Filtrer les groupes après agrégation (GROUP BY) |
| Différence avec WHERE | WHERE filtre les lignes, HAVING filtre les groupes |
| Fonctions compatibles | SUM(), COUNT(), AVG(), MIN(), MAX() |
| Ordre d’exécution | Après GROUP BY, avant ORDER BY |
| Erreur Oracle courante | ORA-00934 si agrégat utilisé dans WHERE |
| Utilisation sans GROUP BY | Déconseillée, même si syntaxiquement acceptée |
2 bonnes pratiques Oracle
- Combinez WHERE et HAVING : utilisez
WHEREpour réduire le nombre de lignes traitées en amont duGROUP BY, etHAVINGpour filtrer les agrégats. Cette combinaison améliore significativement les performances sur de grands volumes de données Oracle. - Évitez de recalculer l’agrégat dans HAVING : sur Oracle 12c et versions supérieures, vous pouvez utiliser un alias de colonne dans
ORDER BY, mais pas dansHAVING. Répétez l’expression agrégée dansHAVINGpour rester compatible avec toutes les versions Oracle.
Aller plus loin avec SQL Oracle
Maintenant que vous maîtrisez la clause HAVING, approfondissez vos compétences en SQL Oracle avec ces sujets complémentaires :
- La clause GROUP BY en SQL Oracle — Comprenez les mécanismes de regroupement qui précèdent et conditionnent l’utilisation de
HAVING. - Les fonctions d’agrégation en SQL Oracle — Maîtrisez
SUM,COUNT,AVG,MINetMAXpour écrire des conditionsHAVINGprécises et performantes. - Les sous-requêtes en SQL Oracle — Découvrez comment combiner
HAVINGavec des sous-requêtes corrélées pour des analyses encore plus puissantes.
