Cours
WHERE et HAVING sont deux clauses essentielles de SQL. Que vous écriviez des requêtes très avancées ou très simples, vous aurez besoin d'utiliser les deux. Vous pouvez considérer WHERE et HAVING comme des frères et sœurs. Ils remplissent tous deux une fonction similaire (filtrage) et apparaissent souvent ensemble. Mais, tout comme les frères et sœurs, ils ont des caractéristiques distinctes et des rôles uniques.
Si vous êtes en train de trier WHERE et HAVING, je vous suggère de vous inscrire à notre cursus de compétences SQL Fundamentals, qui constitue un excellent point de départ. Vous y apprendrez les différentes clauses SQL, l 'ordre d'exécution SQL, l'optimisation des requêtes SQL et bien d'autres choses essentielles.
La réponse courte : Où vs. AVOIR
La réponse courte et la source de confusion pour beaucoup de gens est que WHERE travaille sur des données au niveau des lignes, tandis que HAVING travaille sur des données groupées. Voici une ligne directrice :
-
WHEREfiltre les lignes avant tout regroupement ou agrégation. Elle s'applique à des lignes individuelles et ne peut pas être utilisée avec des fonctions d'agrégation. -
HAVINGfiltre les groupes une fois que le regroupement et l'agrégation ont été effectués. Il s'applique aux résultats des fonctions agrégées et est utilisé en combinaison avecGROUP BY.
Un exemple rapide pour montrer la différence
Prenons un exemple rapide. Si vous souhaitez suivre votre propre flux de travail, vous pouvez télécharger l'ensemble de données sur les locations immobilières à partir de ce dépôt GitHub.
Supposons maintenant que nous ayons besoin de retourner toutes les propriétés de notre ensemble de données dont le prix de location est inférieur à 500 $. Le niveau de détail de chaque ligne de l'ensemble de données (un bien par ligne) correspond au niveau de détail de la condition d'interrogation. Par conséquent, nous utilisons WHERE dans la requête suivante :
SELECT *
FROM rentals
WHERE rental_price < 500
Le résultat serait le suivant. Vous remarquerez que 118 lignes sont renvoyées.

Filtrage simple des lignes avec WHERE. Image par l'auteur.
Supposons maintenant que nous ne souhaitions pas avoir un tableau des biens immobiliers, mais des villes dont le prix de location moyen est inférieur à 2 700 $. Au lieu que chaque ligne corresponde à un bien immobilier, nous regrouperons les lignes et agrégerons le prix de location pour obtenir un prix de location moyen pour chaque ville. Nous utiliserons donc HAVING, comme dans cette requête :
SELECT city, AVG(rental_price) AS average_rent
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;
Et le résultat serait. Remarquez qu'il n'y a qu'un seul résultat.

Filtrage de groupe simple avec HAVING. Image par l'auteur.
WHERE, HAVING et ordre d'exécution SQL
Nous constatons que WHERE fonctionne avec un filtrage au niveau de la ligne, tandis que HAVING fonctionne avec un filtrage au niveau de l'agrégat. La compréhension de cette différence ouvre également la voie à l'apprentissage de l' ordre d'exécution des clauses de SQL.
WHERE est évaluée avant GROUP BY et juste après FROM (et JOIN le cas échéant) ; elle ne peut traiter aucun regroupement ou agrégation. WHERE entre en jeu avant toute agrégation. C'est pourquoi il n'opère que sur des données au niveau de la ligne.
Par ailleurs, HAVING vient après l'exécution de la clause GROUP BY. Cela signifie qu'il intervient après avoir transformé le tableau et l'avoir regroupé à un niveau différent du niveau de granularité du tableau source. HAVING opère sur la nouvelle version transformée du tableau.
Comment utiliser la clause WHERE en SQL
Prenons un peu de recul et examinons chaque clause séparément. Nous pouvons commencer par la clause WHERE.
Syntaxe et instructions WHERE
WHERE peut être utilisé dans trois instructions SQL différentes : SELECT, UPDATE, et DELETE.
WHERE dans les instructions SELECT
Dans les instructions SELECT, qui sont les instructions utilisées pour extraire des données de la base de données, WHERE joue un rôle direct dans le filtrage au niveau des lignes et a sa place bien connue juste après la clause FROM, comme nous pouvons le voir dans la requête suivante :
SELECT column1, column2… etc.
FROM table_name
WHERE condition;
WHERE utilisé avec SELECT est l'endroit où la clause WHERE est le plus souvent confondue avec HAVING.
WHERE dans les instructions UPDATE
En outre, WHERE joue un rôle important dans les instructions UPDATE pour déterminer la ligne où la mise à jour des données doit avoir lieu, comme nous pouvons le voir avec la syntaxe suivante :
UPDATE table_name
SET column_name1 = value1, column_name2 = value2… etc.
WHERE condition;
WHERE dans les instructions DELETE
WHERE est également un complément utile aux instructions DELETE pour préciser les enregistrements (lignes) qui doivent être supprimés, comme nous pouvons le voir ici :
DELETE FROM table_name
WHERE condition;
Comment rédiger les conditions WHERE
WHERE sont écrites sous la forme d'une simple expression logique. Il se compose de trois parties : la variable/l'opérande, la condition et la valeur/le résultat. Examinons les options des conditions WHERE, qui comprennent à la fois des opérateurs logiques et des opérateurs de comparaison.
| Panneau de l'opérateur | Description | Type de données de l'opérande |
|---|---|---|
| = | Egale à (à la date) | Numérique, Texte, Date/horaire, Booléen |
| < | Moins de (avant la date) | Numérique, Date/horaire |
| > | Supérieur à (après la date) | Numérique, Date/horaire |
| <= | Inférieur ou égal à (à la date ou avant) | Numérique, Date/horaire |
| >= | Supérieur ou égal à (à la date ou après la date) | Numérique, Date/horaire |
| <> (!=) | Pas égal à (pas à la date) | Numérique, Texte, Date/horaire, Booléen |
| IN | Égal à plus d'une valeur (à plusieurs dates) | Numérique, Texte, Date/horaire, Booléen (mais cela n'a pas de sens !) |
| LIKE | Correspond à un modèle de texte (à l'aide de caractères génériques) | Texte |
| BETWEEN | Existe dans une gamme | Numérique, Date/horaire |
| ET | Combine plusieurs conditions, toutes doivent être vraies | Logique (booléen) |
| OU | Combine plusieurs conditions, dont l'une au moins doit être vraie | Logique (booléen) |
| NOT | Négation d'une condition | Logique (booléen) |
| EST NULL | Vérifie les valeurs nulles | Tous les types de données |
| IS NOT NULL | Vérifie les valeurs non nulles | Tous les types de données |
Voici un exemple où nous utilisons NOT avec l'opérateur de comparaison IN:
SELECT *
FROM rentals
WHERE city NOT IN ('Cairo', 'Giza');
La déclaration renverra tous les biens qui ne se trouvent ni dans la ville du Caire ni dans celle de Gizeh.

Propriétés en dehors du Caire et de Gizeh. Image par l'auteur.
Cas d'utilisation
Sachant que WHERE fonctionne avec les instructions SELECT, UPDATE et DELETE, nous pouvons prévoir qu'il peut être utilisé pour trois cas d'utilisation : le filtrage au niveau des lignes, l'extraction de données et la manipulation de données.
Filtrage au niveau des lignes
Nous pouvons filtrer les tableaux en fonction d'une ou plusieurs conditions. La requête suivante filtre les lignes pour n'inclure que les propriétés des villas.
SELECT *
FROM rentals
WHERE type = ‘villa’;

Sélection de propriétés de villas. Image par l'auteur.
Recherche de données
WHERE peut être utilisé pour récupérer un point de données spécifique que nous recherchons. Cette méthode est similaire au filtrage au niveau des lignes, mais elle est plus spécifique. En supposant que nous ayons besoin de connaître l'ID du bien qui était disponible le 1er janvier 2022 au Caire, nous pouvons utiliser la requête suivante :
SELECT property_id
FROM rentals
WHERE available_date = '2022-01-01'
AND city = 'Cairo';

Récupération d'un point de données. Image par l'auteur.
Manipulation des données
Enfin, WHERE est une aide précieuse pour modifier des valeurs et supprimer des enregistrements spécifiques dans votre base de données. Par exemple, si nous découvrons que le bien 171 n'accepte pas les animaux, nous pouvons modifier la colonne pet_friendly en utilisant WHERE dans une déclaration UPDATE comme suit :
UPDATE rentals
SET pet_friendly = false
WHERE property_id = 171;
Comment utiliser la clause HAVING en SQL
Il est maintenant temps d'aborder la clause HAVING avec le même niveau de détail.
Syntaxe et déclarations HAVING
Tout d'abord, il faut savoir que la clause HAVING ne peut être utilisée que dans les déclarations SELECT. Par conséquent, la seule syntaxe possible est la suivante :
SELECT grouped_column, aggregate_function(aggregated_column)… etc.
FROM table_name
GROUP BY grouped_column
HAVING condition
Notez que vous pouvez ajouter plus d'une colonne groupée et plus d'une colonne agrégée. Nous en verrons des exemples ci-dessous.
Comment rédiger des conditions de type "HAVING" ?
Comme WHERE, les conditions HAVING sont écrites sous forme d'expressions logiques, mais avec un élément supplémentaire, la fonction d'agrégation. Ainsi, une condition HAVING se compose de 1) une fonction agrégée, 2) une variable/opérande, 3) un opérateur de comparaison et 4) une valeur/résultat.
Fonctions d'agrégation avec HAVING
SQL dispose principalement de cinq fonctions d'agrégation, plus une sixième qui est un cas particulier. Ces fonctions sont les suivantes
| Fonction agrégée | Type de données approprié |
|---|---|
| SUM() | Numérique |
| AVG() | Numérique |
| MIN() | Numérique, Texte, Date/horaire |
| MAX() | Numérique, Texte, Date/horaire |
| COUNT() | Numérique, Texte, Date/horaire, Booléen |
Prenons un exemple. Ici, nous utilisons la fonction COUNT() avec GROUP BY pour créer un tableau de fréquences, et nous utilisons la condition HAVING comme filtre. Plus précisément, nous devons connaître les villes qui sont mentionnées 150 fois ou moins, ce qui, dans ce contexte, correspond au nombre d'enregistrements. Nous pouvons utiliser cette requête :
SELECT city, COUNT(*) AS properties_count
FROM rentals
GROUP BY city
HAVING COUNT(*) <= 150;

Utilisation de COUNT() avec HAVING. Image par l'auteur.
Comparaison et opérateurs logiques
HAVING accepte tous les opérateurs logiques et de comparaison acceptés par WHERE. La seule différence est que le type de données approprié avec HAVING dépend avant tout de la fonction d'agrégation, comme nous pouvons le voir dans le tableau ci-dessus.
Exemples d'utilisation
Contrairement à WHERE, HAVING ne peut pas être utilisé dans les déclarations UPDATE et DELETE; HAVING n'est utilisé que pour la recherche de données. En gros, cela se traduit par deux scénarios :
Filtrage au niveau du groupe
C'est l'usage courant et normal de HAVING. Vous pouvez par exemple ne retenir que les villes où le prix moyen des loyers est inférieur à 2 700 $.
SELECT city, AVG(rental_price) AS avg_price
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;
Filtrage à une rangée
Il s'agit d'un cas peu courant, mais HAVING peut être utilisé pour renvoyer une agrégation d'une seule ligne, comme une métrique ou un indicateur de performance clé, uniquement si elle remplit une certaine condition. Ceci peut être réalisé par l'utilisation de HAVING sans GROUP BY. Dans l'exemple suivant, nous ne renvoyons le prix de location moyen que s'il est inférieur à 2 800 $. Si la mesure remplit la condition, nous obtiendrons un résultat sur une seule ligne. Dans le cas contraire, nous aurions un tableau vide.
SELECT AVG(rental_price) as avg_price
FROM rentals
HAVING AVG(rental_price) > 2800;
Combiner WHERE et HAVING
WHERE et HAVING peuvent être combinés pour filtrer les tableaux avant et après l'agrégation. Dans l'exemple suivant, nous renvoyons le nombre de biens dans chaque ville, en ne comptant que les biens qui acceptent les animaux et en filtrant les villes qui ont plus de 80 biens.
SELECT city, COUNT(*) AS number_properties
FROM rentals
WHERE pet_friendly = true
GROUP BY city
HAVING COUNT(*) > 80;

Combinaison de base de WHERE et HAVING. Image par l'auteur.
La différence entre WHERE et HAVING dans les performances
Nous savons que la clause WHERE est appliquée avant le regroupement ou l'agrégation. Mais nous devons également savoir que, pour cette raison, parce qu'il réduit le nombre de lignes traitées au début de la requête, WHERE est plus efficace pour filtrer des lignes individuelles.
Nous savons, par ailleurs, que la clause HAVING est appliquée après l'agrégation et filtre l'ensemble des résultats sur la base des données groupées. C'est pourquoi, parce qu'il traite les données après que toutes les lignes ont été regroupées, il est généralement moins efficace que WHERE, bien qu'il soit toujours nécessaire pour les conditions impliquant des fonctions agrégées.
Examinons cette requête :
SELECT city, COUNT(*)
FROM rentals
GROUP BY city
HAVING rental_price < 2700;
Cette requête est inefficace car la condition rental_price ne dépend d'aucune agrégation - elle filtre des lignes individuelles. Cette requête regroupe d'abord toutes les locations par ville, les compte, puis filtre le résultat, ce qui est inefficace car cela traite des lignes inutiles. Pour cette raison, cette requête aurait été plus rapide :
SELECT city, COUNT(*)
FROM rentals
WHERE rental_price < 2700
GROUP BY city;
Conseils d'optimisation WHERE et HAVING
Sur la base de ce qui précède, nous pouvons voir certaines des bonnes pratiques qui peuvent optimiser notre utilisation des clauses WHERE et HAVING. Ceci est important si vous avez de grands ensembles de données.
-
Soyez très sélectif : Filtrez en fonction des valeurs que vous souhaitez filtrer et pas plus. Cela permettra de réduire le nombre de lignes dans la vue et donc d'améliorer l'efficacité de la requête.
-
Soyez simple : Supprimez les conditions, les agrégations et les caractères d'imprimerie inutiles. Tous ces avantages ont un prix calculatoire.
-
Filtre précoce : Si vous effectuez une agrégation au niveau du groupe, préfiltrez les lignes avec
WHEREpour accélérer le processus de regroupement. Ce faisant, vous réduisez le nombre de lignes à traiter dans le regroupement.
Tableau de comparaison
Résumons nos réflexions dans un tableau pratique :
| Comparaison | WHERE | AVOIR |
|---|---|---|
| Objectif principal | Filtrage au niveau des lignes | Filtrage au niveau du groupe |
| Syntaxe de base | SELECT colonne1, colonne2... FROM nom_table WHERE condition ; | SELECT colonne_groupée, fonction_agrégée(colonne_agrégée)... FROM nom_table GROUP BY colonne_groupée HAVING condition ; |
| Ordre d'évaluation | Avant GROUP BY | Après GROUP BY |
| Déclarations compatibles | SÉLECTIONNER, METTRE À JOUR, SUPPRIMER | SELECTIONNER |
| Conditions | Impossible d'inclure des fonctions agrégées | Doit inclure des fonctions agrégées |
| Cas d'utilisation | Filtrage au niveau des lignes Extraction des données Manipulation des données | Filtrage au niveau du groupe Filtrage sur une seule ligne |
| Sous-requêtes | Peut fonctionner avec des sous-requêtes | Doit être écrit sous forme d'ETC |
Conclusion
Tout au long de l'article, nous avons exploré la principale différence entre WHERE et HAVING en SQL, à savoir que la clause WHERE filtre les lignes avant l'agrégation, tandis que la clause HAVING filtre les données groupées après l'agrégation. Nous avons également exploré certaines différences moins connues, comme le fait que WHERE peut fonctionner avec les déclarations SELECT, UPDATE et DELETE, mais que HAVING ne fonctionne qu'avec SELECT. Nous avons également parlé de la performance.
L'aide-mémoire de DataCamp sur les bases de SQL fournit une synthèse intéressante des clauses WHERE et HAVING, ainsi que des conseils sur la manière d'effectuer des filtrages en SQL. Par ailleurs, si vous débutez dans le domaine du langage SQL, vous pouvez consulter le cursus de compétences SQL Fundamentals et le cursus de carrière Associate Data Analyst in SQL.

Islam est consultant en données à l'Institut KPI. Issu d'une formation en journalisme, Islam s'intéresse à divers domaines, dont l'écriture, la philosophie, les médias, la technologie et la culture.
Questions fréquemment posées
Quelle est la différence entre OÙ et AVOIR ?
WHERE effectue un filtrage au niveau de la ligne, tandis que HAVING effectue un filtrage au niveau du groupe.
Puis-je combiner WHERE et HAVING dans une même requête ?
Oui, et il est fortement recommandé d'utiliser WHERE si vous avez l'intention d'utiliser HAVING.
Est-ce que WHERE peut fonctionner avec des fonctions agrégées comme HAVING ?
Non, seul HAVING peut utiliser les fonctions agrégées.
Est-ce que WHERE et HAVING fonctionnent avec les mêmes opérateurs logiques et de comparaison ?
Oui, les deux fonctionnent avec les mêmes opérateurs car les conditions WHERE et HAVING sont écrites sous forme d'expressions logiques.
Puis-je utiliser HAVING sans GROUP BY ?
HAVING est généralement utilisé après le regroupement avec GROUP BY. La seule exception à cette règle est le filtrage des vues à valeur unique (comme le calcul d'une métrique).