SQL GROUP BY et fonctions d'agrégation : résumez vos données

Published: 2026-04-08

GROUP BY regroupe plusieurs lignes qui partagent la même valeur dans une ou plusieurs colonnes en une seule ligne de synthèse. Combiné avec des fonctions d’agrégation comme COUNT, SUM, AVG, MIN et MAX, c’est la base de presque toutes les requêtes de reporting et d’analytique. GROUP BY est pris en charge dans toutes les bases SQL, y compris SQLite, PostgreSQL, MySQL, SQL Server et Oracle.

Données d’exemple

Nous utilisons deux tables dans tous les exemples :

Table employees :

id name department hire_date salary
1 Alice Engineering 2023-01-15 95000
2 Bob Engineering 2023-06-01 85000
3 Carol Engineering 2024-03-10 85000
4 Dave Sales 2023-02-20 72000
5 Eve Sales 2023-09-05 68000
6 Frank Sales 2024-01-15 65000
7 Grace Marketing 2023-04-01 82000
8 Henry Marketing 2024-06-01 70000

Table orders :

id customer product category quantity unit_price order_date status
1 Acme Corp Laptop Pro Electronics 3 1299.99 2026-01-05 delivered
2 Acme Corp Wireless Mouse Electronics 10 29.99 2026-01-12 delivered
3 Globex Office Chair Furniture 5 249.99 2026-01-18 delivered
4 Globex Standing Desk Furniture 2 599.99 2026-01-20 shipped
5 Initech Notebook Pack Stationery 20 12.99 2026-02-03 delivered
6 Initech Pen Set Stationery 15 8.99 2026-02-07 delivered
7 Acme Corp Monitor 27" Electronics 4 399.99 2026-02-14 delivered
8 Umbrella Ltd Laptop Pro Electronics 2 1299.99 2026-02-20 cancelled
9 Umbrella Ltd Desk Lamp Furniture 8 39.99 2026-03-01 delivered
10 Globex Wireless Mouse Electronics 12 29.99 2026-03-05 shipped
11 Initech Monitor 27" Electronics 1 399.99 2026-03-10 delivered
12 Acme Corp Standing Desk Furniture 1 599.99 2026-03-15 processing
Explorer le jeu de données dans DbGate Lite

Syntaxe de GROUP BY

SELECT column1, aggregate_function(column2)
FROM table_name
WHERE condition
GROUP BY column1
HAVING aggregate_condition
ORDER BY column1;
  • GROUP BY — une ou plusieurs colonnes dont les combinaisons de valeurs distinctes définissent chaque groupe
  • Fonctions d’agrégation — calculent une seule valeur à partir de toutes les lignes du groupe
  • HAVING — filtre les groupes (comme WHERE, mais pour les résultats groupés)
  • Chaque colonne dans SELECT qui n’est pas à l’intérieur d’une agrégation doit apparaître dans GROUP BY

Ordre d’exécution SQL

Les clauses SQL sont écrites dans un certain ordre mais exécutées dans un ordre différent. Comprendre cela aide à expliquer pourquoi HAVING peut référencer des fonctions d’agrégation mais pas WHERE, et pourquoi vous ne pouvez pas utiliser un alias de SELECT dans une clause HAVING.

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
Étape Clause Ce qui se passe
1 FROM Charge la ou les tables et évalue les JOIN
2 WHERE Filtre les lignes individuelles — les fonctions d’agrégation ne sont pas autorisées ici
3 GROUP BY Regroupe les lignes restantes en groupes
4 HAVING Filtre les groupes — les fonctions d’agrégation sont autorisées ici
5 SELECT Calcule les colonnes de sortie et les alias
6 ORDER BY Trie le jeu de résultats final

C’est pourquoi WHERE status = 'delivered' s’exécute avant le regroupement (filtre rapide au niveau des lignes), tandis que HAVING COUNT(*) > 2 s’exécute après le regroupement (filtre des groupes entiers).

COUNT()

COUNT(*) compte toutes les lignes d’un groupe. COUNT(column) compte les valeurs non NULL dans cette colonne.

Exemple : nombre d’employés par département

Exemple : nombre de commandes par client

Exemple : compter les commandes livrées vs autres statuts

Comptez uniquement les commandes correspondant à une condition en utilisant COUNT avec une expression CASE :

SUM()

SUM(column) additionne toutes les valeurs du groupe pour une colonne numérique.

Exemple : masse salariale totale par département

Exemple : chiffre d’affaires total par catégorie

Calculez le chiffre d’affaires comme quantity * unit_price :

Exemple : chiffre d’affaires par client et par catégorie

Regroupez par plusieurs colonnes pour détailler davantage le chiffre d’affaires :

AVG()

AVG(column) renvoie la moyenne arithmétique de toutes les valeurs non NULL du groupe.

Exemple : salaire moyen par département

Exemple : valeur moyenne de commande par client

MIN() et MAX()

MIN(column) et MAX(column) renvoient respectivement les plus petites et plus grandes valeurs du groupe.

Exemple : fourchette de salaires par département

Exemple : première et dernière date de commande par client

Combiner plusieurs agrégations

Vous pouvez combiner n’importe quel nombre de fonctions d’agrégation dans une seule requête.

Exemple : synthèse complète par département

Exemple : synthèse des commandes par client

HAVING

HAVING filtre les groupes après agrégation — c’est l’équivalent de WHERE pour les résultats groupés.

Exemple : départements avec plus de deux employés

Exemple : clients avec un chiffre d’affaires total supérieur à 2000

Exemple : catégories avec une valeur moyenne de commande inférieure à 500

WHERE vs. HAVING

WHERE filtre les lignes individuelles avant le regroupement. HAVING filtre les groupes après l’agrégation.

Exemple : chiffre d’affaires des seules commandes livrées par client

Utilisez WHERE pour exclure des lignes avant le regroupement, puis HAVING pour filtrer les résultats :

GROUP BY avec des JOIN

Vous pouvez regrouper des données couvrant plusieurs tables en les joignant d’abord.

Exemple : chiffre d’affaires par département via une jointure sur employees

Exemple : nombre de commandes et chiffre d’affaires par catégorie et par mois

GROUP BY avec des expressions

Vous pouvez regrouper par des expressions calculées, pas seulement par des colonnes simples.

Exemple : employés embauchés par année

Exemple : commandes par mois

COUNT(DISTINCT)

COUNT(DISTINCT column) compte le nombre de valeurs uniques dans le groupe.

Exemple : nombre de produits uniques commandés par client

Filtrer les groupes avec plusieurs conditions

HAVING prend en charge toute expression booléenne, y compris les combinaisons AND/OR.

Exemple : clients actifs à forte valeur

Trouvez les clients avec plus d’une commande et un chiffre d’affaires total supérieur à 1000 :

Exemple pratique : rapport de ventes

Combinez tout pour obtenir un rapport de ventes complet.

Exemple : rapport de performance par catégorie

Exemple : produit le plus rentable

GROUP BY vs. fonctions de fenêtre

GROUP BY regroupe les lignes en une ligne par groupe. Les fonctions de fenêtre conservent toutes les lignes et ajoutent une colonne calculée — voir le tutoriel sur les fonctions de fenêtre SQL pour plus de détails.

Exemple : GROUP BY renvoie une ligne par département

Exemple : une fonction de fenêtre conserve toutes les lignes

Cas d’usage courants de GROUP BY

  • Tableaux de bord de reporting — Résumer totaux, moyennes et comptes par catégorie ou période
  • Analyse des effectifs — Compter les employés, utilisateurs ou enregistrements par groupe
  • Répartition du chiffre d’affaires — Total et moyenne par produit, région ou client
  • Analyse de tendances — Regrouper par mois ou année pour repérer les évolutions dans le temps
  • Top-N par groupe — Combiner avec des sous-requêtes ou des CTE pour trouver le meilleur élément dans chaque groupe
  • Validation des données — Compter les doublons ou les valeurs NULL par groupe
  • Analyse de cohortes — Regrouper les utilisateurs par date d’inscription ou segment de comportement

Conseils de performance

  1. Indexer les colonnes de GROUP BY — Les index sur les colonnes de regroupement accélèrent l’étape de tri et de regroupement
  2. Filtrer tôt avec WHERE — Réduire les lignes avant le regroupement avec WHERE est plus rapide que filtrer après avec HAVING
  3. Éviter SELECT * — Ne sélectionnez que les colonnes dont vous avez réellement besoin ; les agrégations profitent de données plus étroites
  4. Utiliser des index couvrants — Un index qui inclut à la fois la colonne de GROUP BY et la colonne agrégée peut éviter un scan complet de la table
  5. Envisager des vues matérialisées — Pour des agrégations fréquentes sur de grandes tables, certaines bases permettent des synthèses pré-calculées

Récapitulatif

  • GROUP BY regroupe les lignes qui partagent les mêmes valeurs de colonnes en une ligne de synthèse par combinaison unique
  • COUNT(*) compte toutes les lignes ; COUNT(column) compte les valeurs non NULL ; COUNT(DISTINCT column) compte les valeurs uniques
  • SUM totalise les valeurs numériques ; AVG calcule la moyenne ; MIN / MAX trouvent les bornes
  • Chaque colonne de SELECT doit soit apparaître dans GROUP BY, soit être enveloppée dans une fonction d’agrégation
  • WHERE filtre les lignes avant le regroupement ; HAVING filtre les groupes après agrégation
  • Vous pouvez faire un GROUP BY sur des expressions (par exemple SUBSTR(date, 1, 7) pour un regroupement au niveau du mois)
  • Joindre des tables avant le regroupement vous permet de combiner des données de plusieurs sources dans un seul rapport
  • Utilisez des fonctions de fenêtre plutôt que GROUP BY lorsque vous avez besoin de métriques au niveau du groupe sans perdre les lignes individuelles

Essayez de combiner GROUP BY avec des JOIN, des expressions CASE et des clauses HAVING pour construire les rapports dont votre analyse de données a besoin !