Data Analyst

GROUP BY et HAVING : construire des KPI en SQL

Transformez des lignes de ventes en indicateurs fiables par ville, catégorie ou période.

Équipe SQL.tn10 min
Illustration de lignes de données regroupées puis transformées en indicateurs visuels

Passer du détail à un indicateur

Une table de commandes contient généralement une ligne par transaction. Un tableau de bord attend plutôt une ligne par ville, par catégorie ou par mois, accompagnée d’indicateurs comme le chiffre d’affaires et le panier moyen.

GROUP BY change le niveau de détail du résultat. Toutes les lignes partageant la même valeur sont rassemblées avant le calcul des fonctions d’agrégation.

Les données de cet article sont fictives. Les montants et résultats servent uniquement à expliquer la méthode.

COUNT, SUM et AVG répondent à trois questions différentes

COUNT compte, SUM additionne et AVG calcule une moyenne. Ces fonctions réduisent plusieurs lignes en une valeur synthétique.

Dans un rapport de ventes, vous pouvez compter les commandes, additionner leur montant et calculer le panier moyen dans la même requête.

  • COUNT(*) compte les lignes du groupe.
  • COUNT(colonne) ignore les valeurs NULL de cette colonne.
  • SUM(montant) additionne les montants non NULL.
  • AVG(montant) calcule leur moyenne.
Indicateurs globaux sur les commandes
SELECT
  COUNT(*) AS nombre_commandes,
  SUM(montant) AS chiffre_affaires,
  ROUND(AVG(montant), 2) AS panier_moyen
FROM commandes;

GROUP BY crée une ligne par groupe

Pour obtenir une ligne par ville, ajoutez ville au résultat et à la clause GROUP BY. Chaque agrégation est alors calculée séparément pour Tunis, Sfax et les autres villes présentes.

En règle pratique, toute colonne affichée dans SELECT qui n’est pas agrégée doit figurer dans GROUP BY.

Nombre de clients par ville
SELECT
  ville,
  COUNT(*) AS nombre_clients
FROM clients
GROUP BY ville
ORDER BY nombre_clients DESC;

WHERE filtre les lignes avant le calcul

WHERE retire des lignes avant la formation des groupes. Pour construire les KPI de l’année 2026, filtrez les commandes sur leur date avant d’exécuter GROUP BY.

Cette distinction est importante : les lignes exclues par WHERE ne participent ni au comptage, ni à la somme, ni à la moyenne.

Chiffre d’affaires 2026 par client
SELECT
  id_client,
  SUM(montant) AS chiffre_affaires
FROM commandes
WHERE date_commande >= DATE '2026-01-01'
  AND date_commande < DATE '2027-01-01'
GROUP BY id_client;

HAVING filtre les groupes après le calcul

HAVING intervient après l’agrégation. Il permet par exemple de conserver uniquement les villes ayant au moins cinq commandes ou un chiffre d’affaires supérieur à un seuil.

Utilisez WHERE pour une condition portant sur une ligne d’origine et HAVING pour une condition portant sur un groupe ou une agrégation.

Conserver les clients ayant au moins cinq commandes
SELECT
  id_client,
  COUNT(*) AS nombre_commandes
FROM commandes
GROUP BY id_client
HAVING COUNT(*) >= 5
ORDER BY nombre_commandes DESC;

Assembler une requête KPI complète

Pour analyser les ventes par ville, il faut d’abord relier les commandes aux clients, filtrer la période, regrouper par ville puis filtrer les groupes peu représentatifs.

L’alias chiffre_affaires peut être réutilisé dans ORDER BY avec PostgreSQL. La clause HAVING conserve l’expression d’agrégation complète pour rester explicite.

KPI de ventes par ville
SELECT
  c.ville,
  COUNT(co.id_commande) AS nombre_commandes,
  SUM(co.montant) AS chiffre_affaires,
  ROUND(AVG(co.montant), 2) AS panier_moyen
FROM clients AS c
INNER JOIN commandes AS co
  ON c.id_client = co.id_client
WHERE co.date_commande >= DATE '2026-01-01'
  AND co.date_commande < DATE '2027-01-01'
GROUP BY c.ville
HAVING COUNT(co.id_commande) >= 5
ORDER BY chiffre_affaires DESC;

Les erreurs qui faussent un KPI

Une agrégation correcte dépend autant du niveau de détail que de la formule. Avant de publier un indicateur, vérifiez ce que représente exactement chaque ligne du résultat.

  • Afficher une colonne non agrégée sans l’ajouter à GROUP BY.
  • Utiliser WHERE COUNT(*) > 5 au lieu de HAVING.
  • Compter après une jointure qui a multiplié les lignes.
  • Oublier que COUNT(colonne) ignore les valeurs NULL.
  • Mélanger des périodes différentes dans le même indicateur.
Contrôle simple : calculez d’abord le total général, puis comparez-le à la somme des groupes. Un écart doit être expliqué par le filtre ou les valeurs NULL.

Votre checklist avant de partager le résultat

Définissez le niveau attendu — une ligne par ville, client ou mois — puis choisissez les agrégations. Appliquez le filtre de période avec WHERE, le seuil métier avec HAVING et un tri lisible avec ORDER BY.

Enfin, vérifiez quelques groupes à la main et documentez la définition du KPI. Une requête courte mais ambiguë reste moins utile qu’un calcul explicite et reproductible.

Situez votre niveau SQL.

Testez vos acquis sur dix questions aléatoires et obtenez le prochain parcours conseillé.

Passer le test gratuit
GROUP BY et HAVING en SQL : guide pratique — SQL.tn