Comment utiliser WHERE avec GROUP BY en SQL
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 :
country | population | yearly_change | net_change | med_age | urban_pop_pct | world_share |
---|---|---|---|---|---|---|
China | 1,439,323,776 | 0.0039 | 5,540,090 | 38 | .61 | .1847 |
India | 1,380,004,385 | 0.0099 | 13,586,631 | 28 | .35 | .1770 |
United States | 331,002,651 | 0.0059 | 1,937,734 | 38 | .83 | .0425 |
Indonesia | 273,523,615 | .0107 | 2,898,047 | 30 | .56 | .0351 |
Pakistan | 220,892,340 | .02 | 4,327,022 | 23 | .35 | .0283 |
Brazil | 212,559,417 | 0072 | 1,509,890 | 33 | .88 | .0273 |
Nigeria | 206,139,589 | .0258 | 5,175,990 | 18 | .52 | .0264 |
Bangladesh | 164,689,383 | .0101 | 1,643,222 | 28 | .39 | .0211 |
Russia | 145,934,462 | .0004 | 62,206 | 40 | .74 | .0187 |
Mexico | 128,932,753 | .0106 | 1,357,224 | 29 | .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 :
country | population | yearly_change | net_change | med_age | urban_pop_pct | world_share |
---|---|---|---|---|---|---|
China | 1439323776 | 0.0039 | 5540090 | 38 | .61 | .1847 |
India | 1380004385 | 0.0099 | 13586631 | 28 | .35 | .1770 |
United States | 331002651 | 0.0059 | 1937734 | 38 | .83 | .0425 |
Indonesia | 273523615 | .0107 | 2898047 | 30 | .56 | .0351 |
Pakistan | 220892340 | .02 | 4327022 | 23 | .35 | .0283 |
Brazil | 212559417 | 0.72% | 1509890 | 33 | 88% | 2.73% |
Nigeria | 206139589 | 2.58% | 5175990 | 18 | 52% | 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 :
country | population | yearly_change | net_change | med_age | urban_pop_pct | world_share |
---|---|---|---|---|---|---|
United States | 331002651 | 0.0059 | 1937734 | 38 | .83 | .0425 |
Brazil | 212559417 | 0.0072 | 1509890 | 33 | .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 :
Description | ProductCategory | Quantity | UnitPrice | CustomerID |
---|---|---|---|---|
KNITTED UNION FLAG HOT WATER BOTTLE | Kitchen | 6 | 3.39 | 17850 |
POPPY'S PLAYHOUSE BEDROOM | Toys | 6 | 2.1 | 17850 |
IVORY KNITTED MUG COSY | Kitchen | 6 | 1.65 | 13047 |
BOX OF VINTAGE JIGSAW BLOCKS | Toys | 3 | 4.95 | 13047 |
RED COAT RACK PARIS FASHION | Clothing | 3 | 4.95 | 13047 |
YELLOW COAT RACK PARIS FASHION | Clothing | 3 | 4.95 | 13047 |
BLUE COAT RACK PARIS FASHION | Clothing | 3 | 4.95 | 13047 |
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 :
ProductCategory | Quantity |
---|---|
Kitchen | 12 |
Toys | 9 |
Clothing | 9 |
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 :
CustomerID | ProductCategory | Quantity |
---|---|---|
17850 | Kitchen | 6 |
17850 | Toys | 6 |
13047 | Kitchen | 6 |
13047 | Toys | 3 |
13047 | Clothing | 9 |
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 :
ProductCategory | AvgUnitPrice |
---|---|
Kitchen | 2.52 |
Toys | 3.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 :
ProductCategory | Quantity |
---|---|
Kitchen | 6 |
Toys | 3 |
Clothing | 9 |
É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 :
ProductCategory | Quantity |
---|---|
Kitchen | 12 |
Toys | 9 |
Clothing | 9 |
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 :
ProductCategory | AvgUnitPrice |
---|---|
Toys | 3.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.