Retour à la liste des articles Articles
8 minutes de lecture

Comment utiliser WHERE avec GROUP BY en SQL

Dans cet article, nous allons voir comment combiner les clauses WHERE et GROUP BY en SQL. Si vous écrivez quotidiennement du SQL, vous vous rendrez rapidement compte de la fréquence d'utilisation des clauses WHERE et GROUP BY. WHERE est un élément essentiel de la plupart des requêtes. Elle vous permet de filtrer de grands ensembles de données pour n'en retenir que les éléments qui vous intéressent. GROUP BY est l'un des outils les plus puissants dont dispose un analyste pour agréger des données. À la fin de cet article, vous comprendrez comment utiliser efficacement ces deux clauses tout en évitant les pièges courants.

Lorsqu'il s'agit d'écrire du SQL, considérez chaque clause (SELECT, WHERE, GROUP BY, etc.) comme un outil distinct. Au fur et à mesure que vous apprenez la syntaxe SQL, vous ajoutez cet outil à votre boîte à outils. Comme vous pouvez l'imaginer, un mécanicien ne disposant que de quelques outils ne sera pas très efficace. Je ne vous recommande pas de confier votre voiture à quelqu'un qui ne dispose que de quelques outils. Il en va de même pour l'analyse des données. Plus vous avez d'outils à votre disposition, plus vous pouvez analyser rapidement et efficacement différents ensembles de données.

L'une des façons les plus complètes d'acquérir des outils SQL est de suivre notre cours interactif SQL pour les débutants. Il comporte 129 exercices et couvre les compétences SQL de base et intermédiaires, vous dotant ainsi de tout ce que vous devez apprendre pour devenir un analyste de données efficace.

Commençons par examiner en profondeur WHERE et GROUP BY séparément. Après avoir acquis ces connaissances de base, nous combinerons les deux et libérerons toute leur puissance.

La clause WHERE

Comme indiqué précédemment, la clause WHERE est utilisée pour filtrer un ensemble de données et ne renvoyer que les enregistrements qui correspondent à certains critères spécifiques. Prenons l'ensemble de données suivant, qui comprend les populations des pays pour 2022.

À des fins d'illustration, nous dirons que ces données sont hébergées dans une table appelée world_populations et qu'elles ne comprennent que les 10 pays les plus peuplés. Nous allons examiner ces données en les exécutant :

SELECT *
FROM world_populations

Voici le résultat :

countrypopulationyearly_changenet_changemed_ageurban_pop_pctworld_share
China1,439,323,7760.00395,540,09038.61.1847
India1,380,004,3850.009913,586,63128.35.1770
United States331,002,6510.00591,937,73438.83.0425
Indonesia273,523,615.01072,898,04730.56.0351
Pakistan220,892,340.024,327,02223.35.0283
Brazil212,559,41700721,509,89033.88.0273
Nigeria206,139,589.02585,175,99018.52.0264
Bangladesh164,689,383.01011,643,22228.39.0211
Russia145,934,462.000462,20640.74.0187
Mexico128,932,753.01061,357,22429.84.0165

OK, nous avons nos données. Maintenant, ajoutons quelques filtres.

Exemple 1

Dans notre premier exemple, nous voulons uniquement voir les pays dont la population est supérieure à 200 millions d'habitants. Pour ce faire, nous allons exécuter la requête suivante :

SELECT *
FROM world_populations
WHERE population > 200000000

Et le résultat :

countrypopulationyearly_changenet_changemed_ageurban_pop_pctworld_share
China14393237760.0039554009038.61.1847
India13800043850.00991358663128.35.1770
United States3310026510.0059193773438.83.0425
Indonesia273523615.0107289804730.56.0351
Pakistan220892340.02432702223.35.0283
Brazil2125594170.72%15098903388%2.73%
Nigeria2061395892.58%51759901852%2.64%

Nous pouvons voir que la clause WHERE a filtré le Bangladesh, la Russie et le Mexique car leurs populations sont inférieures au seuil établi dans notre requête.

Exemple n° 2

La clause WHERE peut également prendre en charge plusieurs filtres. Ne retenons que les pays qui ont connu une évolution annuelle positive du nombre de migrants et dont au moins 80 % de la population vit dans des zones urbaines. Notez que nous avons utilisé AND dans la clause WHERE pour relier ces deux conditions :

SELECT *
FROM world_populations
WHERE migrants > 0
  AND urban_pop_pct > .80

Cette requête renvoie :

countrypopulationyearly_changenet_changemed_ageurban_pop_pctworld_share
United States3310026510.0059193773438.83.0425
Brazil2125594170.0072150989033.88.0273

Il n'y a pas de limite à la quantité de filtrage que vous pouvez effectuer dans une clause WHERE. Pour plus de détails, consultez notre Guide complet de la clause WHERE en SQL.

La clause GROUP BY

Pour comprendre GROUP BY, nous allons utiliser un ensemble de données différent appelé transactions. Il contient des données transactionnelles pour un détaillant en ligne :

DescriptionProductCategoryQuantityUnitPriceCustomerID
KNITTED UNION FLAG HOT WATER BOTTLEKitchen63.3917850
POPPY'S PLAYHOUSE BEDROOMToys62.117850
IVORY KNITTED MUG COSYKitchen61.6513047
BOX OF VINTAGE JIGSAW BLOCKSToys34.9513047
RED COAT RACK PARIS FASHIONClothing34.9513047
YELLOW COAT RACK PARIS FASHIONClothing34.9513047
BLUE COAT RACK PARIS FASHIONClothing34.9513047

Exemple 1

L'opérateur GROUP BY est utilisé pour agréger des données en regroupant les enregistrements qui partagent la même valeur dans un champ spécifié. Pour répondre à la question "Combien d'articles ont été vendus dans chaque catégorie de produits ?", il faut exécuter la requête suivante :

SELECT 
  productCategory,
  SUM(quantity) as quantity
FROM transactions 
GROUP BY productCategory

Voici les résultats :

ProductCategoryQuantity
Kitchen12
Toys9
Clothing9

Il y a deux produits dans la catégorie des produits de cuisine : BOTTERIE D'EAU CHAUDE AVEC DRAPEAU SYNDICAL TISSÉ et TASSERIE IVOIRE TISSÉE COSY. Chacun de ces produits a une quantité de 6 ; par conséquent, la somme totale pour la catégorie de produits de cuisine est de 12.

Il y a deux produits dans la catégorie des jouets. POPPY'S PLAYHOUSE BEDROOM a une quantité de 6 et BOX OF VINTAGE JIGSAW BLOCKS a une quantité de 3, pour une somme totale de 9.

Enfin, il y a trois produits dans la catégorie des vêtements, chacun ayant une quantité de 3. Cela porte la somme totale de la catégorie des vêtements à 9.

Nous ne les passerons pas toutes en revue, mais il existe de nombreux types d'agrégations à la disposition de l'analyste de données. Parmi ceux-ci, citons SUM(), AVG(), COUNT(), MEDIAN(), MIN() et MAX(). Vous trouverez de plus amples informations dans l'article Comment utiliser les fonctions d'agrégation dans la clause WHERE.

Exemple #2

Que faire si nous voulons agréger les quantités pour chaque catégorie de produit et chaque client ? Nous pouvons GROUP BY plusieurs colonnes :

SELECT 
  customerId,
  productCategory,
  SUM(quantity) as quantity
FROM transactions 
GROUP BY customerId, productCategory

Et voici le résultat :

CustomerIDProductCategoryQuantity
17850Kitchen6
17850Toys6
13047Kitchen6
13047Toys3
13047Clothing9

Nous pouvons voir qu'il y a une ligne pour chaque combinaison de client et de catégorie de produit ; nous savons maintenant combien d'articles de chaque catégorie chaque client a acheté.

Pour plus d'informations sur GROUP BY, consultez les articles Using GROUP BY in SQL et GROUP BY in SQL Explained.

Utilisation conjointe de WHERE et GROUP BY

Maintenant que nous avons posé les bases, combinons WHERE et GROUP BY. Il est important de se rappeler que la clause WHERE va filtrer l'ensemble de données avant que la clause GROUP BY ne soit évaluée. De même, la clause WHERE sera toujours placée avant GROUP BY. Si vous la placez après, la requête renverra une erreur.

Exemple #1

Considérez le même ensemble de données et réfléchissez à la façon dont nous répondrions à la question "Quel est le prix unitaire moyen des produits de cuisine et des jouets ?"

Tout d'abord, nous devons filtrer les produits de cuisine et les jouets. Ensuite, nous allons calculer le prix unitaire moyen. Voici la requête :

SELECT
  productCategory,
  AVG(UnitPrice) as AvgUnitPrice
FROM transactions 
WHERE productCategory in(‘Kitchen’, ‘Toys’)
GROUP BY productCategory

Et le résultat est :

ProductCategoryAvgUnitPrice
Kitchen2.52
Toys3.05

Le prix unitaire moyen est calculé uniquement pour les produits de cuisine et de jouets. Toutes les autres catégories sont exclues de la requête.

Exemple #2

Voyons maintenant comment obtenir la quantité totale de produits par catégorie dont le prix unitaire moyen est supérieur à 3. Pour ce faire, nous devons exécuter la requête suivante

SELECT
  productCategory,
  SUM(quantity) as quantity
FROM transactions 
WHERE unitPrice > 3
GROUP BY productCategory

Dans cet exemple, les agrégats sont calculés sur les lignes filtrées. Nous obtenons le résultat suivant :

ProductCategoryQuantity
Kitchen6
Toys3
Clothing9

Étant donné que seuls les produits suivants ont un prix unitaire supérieur à 3 : BOUTEILLE D'EAU CHAUDE AVEC DRAPEAU DE L'UNION TISSÉ, BOÎTE DE BLOCS DE JIGSAW VINTAGE, PORTE MANTEAU ROUGE PARIS FASHION, PORTE MANTEAU JAUNE PARIS FASHION et PORTE MANTEAU BLEU PARIS FASHION, ce sont les seuls produits inclus dans l'agrégation.

Si nous devions exclure la clause WHERE, nous obtiendrions les résultats suivants :

ProductCategoryQuantity
Kitchen12
Toys9
Clothing9

Nous voyons ici que les quantités de tous les produits, quel que soit leur prix unitaire, sont totalisées. La quantité totale est différente pour tous les produits et pour les produits dont le prix unitaire est supérieur à 3.

Exemple #3

Que faire si nous voulons filtrer par une colonne agrégée ? C'est le rôle de la clause HAVING. Vous ne pouvez pas placer une agrégation dans la clause WHERE. La clause HAVING est utilisée à la place de WHERE lors d'un filtrage basé sur des fonctions d'agrégation. Nous pouvons illustrer cela avec un autre exemple. Poursuivons avec l'exemple ci-dessus et filtrons les résultats par catégories de produits dont le prix unitaire moyen est supérieur à 3. Pour ce faire, nous devons écrire

SELECT
  productCategory 
  AVG(UnitPrice) as AvgUnitPrice
FROM transactions 
WHERE productCategory in (‘Kitchen’, ‘Toys’)
GROUP BY productCategory
HAVING AVG(UnitPrice) > 3

Résultat :

ProductCategoryAvgUnitPrice
Toys3.05

La première chose qui se passe est que la clause WHERE limite les données aux seules catégories de cuisine et de produits. La clause GROUP BY agrège ensuite le prix unitaire moyen pour chaque catégorie. Enfin, la clause HAVING filtre davantage les résultats pour inclure uniquement les catégories de produits dont le prix unitaire moyen est supérieur à 3.

Si nous supprimions la clause HAVING, nous verrions que les catégories cuisine et jouets apparaîtraient dans le résultat. Cependant, comme le prix unitaire moyen des articles de cuisine est inférieur à 3, il est filtré lorsque nous ajoutons la clause HAVING.

Pour plus d'exemples, lisez notre article sur la comparaison entre HAVING et WHERE en SQL.

WHERE et GROUP BY - Que faire maintenant ?

Excellent travail ! Vous avez acquis les connaissances de base nécessaires pour combiner les clauses WHERE et GROUP BY en SQL. Vous avez été initié à la différence entre WHERE et HAVING. Plus important encore, vous pouvez combiner ces trois clauses ensemble pour filtrer et agréger les données en fonction de vos besoins.

Vous avez ajouté deux outils supplémentaires à votre boîte à outils et vous êtes prêt à les utiliser. Une excellente façon de renforcer ces connaissances est de suivre notre cours interactif sur SQL pour les débutants. C'est en forgeant qu'on devient forgeron !

N'oubliez pas non plus de consulter tous nos autres articles.