La condition porte-t-elle sur une ligne ou sur un groupe ?
Un statut ou une date appartient à une ligne source : utilisez WHERE. Un total, une moyenne ou un nombre de commandes existe après regroupement : utilisez HAVING.
L’ordre modifie le sens. Exclure des lignes annulées avant SUM n’est pas équivalent à calculer tous les statuts puis masquer certains groupes.
La requête expliquée
Commencez par définir ce que doit représenter une ligne du résultat. Cette décision détermine les colonnes, les regroupements et les contrôles nécessaires.
L’exemple suivant isole le mécanisme principal. Exécutez-le, observez le résultat, puis modifiez une seule clause à la fois pour comprendre son effet.
SELECT id_client, COUNT(*) AS commandes_payees
FROM commandes
WHERE statut = 'Payée'
GROUP BY id_client
HAVING COUNT(*) >= 2;Lire le résultat comme un analyste
WHERE prépare uniquement les commandes payées. GROUP BY crée une ligne par client, puis HAVING conserve les volumes d’au moins deux.
Séparez mentalement ces étapes et contrôlez le nombre de lignes à chacune lorsque la requête devient complexe.
- Formuler le périmètre de lignes.
- Définir le grain des groupes.
- Appliquer le seuil sur l’agrégation.
- Comparer le total global à la somme des groupes.
Les erreurs qui faussent l’analyse
Une requête peut être valide sans répondre correctement à la question. Les erreurs les plus coûteuses sont souvent silencieuses : mauvais périmètre, ligne multipliée ou valeur absente interprétée comme zéro.
Avant de partager le résultat, confrontez-le à un petit échantillon calculé à la main et conservez la définition du périmètre avec la requête.
- Écrire WHERE COUNT(*).
- Filtrer montant >= seuil au lieu de SUM(montant) >= seuil.
- Oublier GROUP BY.
- Comparer des groupes construits avec des périmètres différents.
Passez à la pratique
Faites l’exercice HAVING sur le panier moyen, puis changez le seuil pour observer les groupes retenus.
Le simulateur SQL de SQL.tn exécute uniquement des requêtes de lecture sur des données fictives dans votre navigateur. Vous pouvez essayer plusieurs écritures et comparer leur résultat sans installer de logiciel.
Testez la différence sur des données concrètes
Qui a payé plus de 100 € au total ? Emma a payé 60 € puis 70 €. James a payé 80 € et possède aussi une commande annulée de 100 €. Olivia a payé exactement 100 €.
| customer_name | amount | status |
|---|---|---|
| Emma | 60 | paid |
| Emma | 70 | paid |
| James | 80 | paid |
| James | 100 | cancelled |
| Olivia | 100 | paid |
SELECT customer_name, SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY customer_name
HAVING SUM(amount) > 100
ORDER BY customer_name;WHERE retire la commande annulée avant le calcul. GROUP BY réunit les achats par client. HAVING garde ensuite les totaux strictement supérieurs à 100 € : seule Emma reste, avec 130 €.
Essayez de remplacer HAVING par AND amount > 100 dans WHERE : aucune ligne ne reste. Vous avez filtré les commandes individuelles, pas les totaux. Avec >= 100 dans HAVING, Olivia serait aussi retenue.
Simulateur SQL dans le navigateur
Testez la différence sur des données concrètes
Exécutez une requête de lecture sur les données fictives de cet exercice. Rien n’est envoyé à SQL.tn.
