Ces 4 patterns reviennent dans presque tous les entretiens data. Modai Lab te soumet des requêtes cassées : à toi d'identifier WHERE ou HAVING mal placé.
_Score immédiat · Explication de chaque erreur · Niveau calibré automatiquement_
PARTIE 3 — Cas business réels
Cas réel 1 — E-commerce : taux de conversion par source d'acquisition
Objectif : identifier les sources qui génèrent plus de 100 acheteurs avec un taux de conversion > 5%.
-- ❌ Version avec les deux filtres au mauvais endroit
SELECT
source,
COUNT(DISTINCT user_id) AS visiteurs,
COUNT(DISTINCTCASEWHEN a_achete THEN user_id END) AS acheteurs
FROM sessions
HAVINGCOUNT(DISTINCT user_id) > -- ❌ devrait être dans WHERE ou HAVING mais cohérent ?
ANDCOUNT(DISTINCTCASEWHEN a_achete THEN user_id END) * .
/ COUNT(DISTINCT user_id) > .
GROUPBY source;
-- Erreur : HAVING avant GROUP BY syntaxiquement
where-vs-having-erreur-agregations · 12
-- ✅ Version correcte
SELECT
source,
COUNT(DISTINCT user_id) AS visiteurs,
COUNT(DISTINCTCASEWHEN a_achete THEN user_id END) AS acheteurs,
ROUND(
. * COUNT(DISTINCTCASEWHEN a_achete THEN user_id END)
/ NULLIF(COUNT(DISTINCT user_id), ),
) AS taux_conv_pct
FROM sessions
WHERE created_at >= '2024-01-01'-- WHERE : filtre sur colonne brute
GROUPBY source
HAVINGCOUNT(DISTINCT user_id) > -- HAVING : filtre sur agrégat
ANDCOUNT(DISTINCTCASEWHEN a_achete THEN user_id END) * .
/ NULLIF(COUNT(DISTINCT user_id), ) > .
ORDERBY taux_conv_pct DESC;
where-vs-having-erreur-agregations · 13
Cas réel 2 — SaaS : détecter les comptes à risque de churn
Objectif : comptes actifs depuis plus de 6 mois avec moins de 5 connexions dans les 30 derniers jours.
-- ❌ Version fausse : WHERE sur un agrégat
SELECT
account_id,
COUNT(*) AS nb_connexions_recentes
FROM logins
WHERE created_at > NOW() - INTERVAL '30 days'
ANDCOUNT(*) < -- ❌ erreur SQL : agrégat dans WHERE
GROUPBY account_id;
where-vs-having-erreur-agregations · 14
-- ✅ Version correcte
SELECT
a.account_id,
a.created_at AS date_inscription,
COUNT(l.id) AS nb_connexions_30j
FROM accounts a
LEFTJOIN logins l
ON a.account_id = l.account_id
AND l.created_at > NOW() - INTERVAL '30 days'-- filtre dans le ON, pas WHERE
WHERE a.created_at < NOW() - INTERVAL '6 months'-- WHERE : filtre sur colonne brute (ancienneté)
AND a.statut = 'actif'
GROUPBY a.account_id, a.created_at
HAVINGCOUNT(l.id) < -- HAVING : filtre sur l'agrégat
ORDERBY nb_connexions_30j ASC;
where-vs-having-erreur-agregations · 15
Cas réel 3 — Finance : identifier les fournisseurs à auditer
Objectif : fournisseurs avec plus de 20 factures dont le montant moyen est supérieur à 5 000€ et au moins une facture en retard.
-- ❌ Mélange WHERE/HAVING incohérent
SELECT
fournisseur_id,
COUNT(*) AS nb_factures,
AVG(montant) AS montant_moyen
FROM factures
WHEREAVG(montant) > -- ❌ agrégat dans WHERE
AND statut = 'en_retard'-- fausse le COUNT : ne compte que les retards
GROUPBY fournisseur_id
HAVINGCOUNT(*) > ;
where-vs-having-erreur-agregations · 16
-- ✅ Version correcte avec logique séparée proprement
SELECT
fournisseur_id,
COUNT(*) AS nb_factures_total,
AVG(montant) AS montant_moyen,
COUNT(CASEWHEN statut = 'en_retard'THENEND) AS nb_retards
FROM factures
WHERE annee_fiscale = -- WHERE : périmètre temporel (colonne brute)
GROUPBY fournisseur_id
HAVINGCOUNT(*) > -- HAVING : filtre sur nb total de factures
ANDAVG(montant) > -- HAVING : filtre sur la moyenne
ANDCOUNT(CASEWHEN statut = 'en_retard'THENEND) >= -- HAVING : au moins un retard
ORDERBY nb_retards DESC, montant_moyen DESC;
where-vs-having-erreur-agregations · 17
🧪 Pratique sur les cas métiers réels
Sales, RH, Finance, E-commerce : Modai Lab propose ces scénarios avec de vraies données imparfaites. Le feedback t'indique exactement quel filtre est mal placé et pourquoi.
_Scénarios data réels · Feedback senior · Progression mesurée_
PARTIE 4 — Prompt Claude pour détecter les filtres mal placés
Copie ce prompt avec ta requête pour obtenir un diagnostic en 30 secondes.
Prompt d'audit complet
Tu es un expert SQL. Audite la requête suivante et identifie les erreurs
liées à WHERE et HAVING.
REQUÊTE À AUDITER :
[coller ta requête]
CONTEXTE MÉTIER :
- Objectif : [ex: compter les clients avec plus de 3 commandes livrées]
- Résultat attendu : [ex: une ligne par client avec son nombre de commandes]
Analyse ces points dans l'ordre :
1. ORDRE D'EXÉCUTION
- Quelles clauses s'exécutent avant GROUP BY ?
- Quelles clauses s'exécutent après GROUP BY ?
- Y a-t-il des alias du SELECT utilisés dans WHERE ou HAVING ?
2. WHERE
- Tous les filtres WHERE portent-ils sur des colonnes brutes (pas d'agrégats) ?
- Y a-t-il des filtres WHERE qui devraient être dans HAVING ?
- Un filtre WHERE exclut-il des lignes qui devraient entrer dans l'agrégation ?
3. HAVING
- Tous les filtres HAVING portent-ils sur des agrégats ou des expressions agrégées ?
- Y a-t-il des filtres HAVING qui devraient être dans WHERE (pour des raisons de performance) ?
- Les filtres HAVING sont-ils portables entre SGBD (pas d'alias) ?
4. CORRECTION
- Montre la requête corrigée avec commentaires
- Explique l'impact sur le résultat si les filtres étaient mal placés
Format : ❌ pour chaque problème trouvé, ✅ pour les points corrects.
where-vs-having-erreur-agregations · 18
Prompt rapide
Audite cette requête SQL pour détecter les filtres WHERE et HAVING mal placés.
Indique pour chaque filtre s'il est au bon endroit et pourquoi.
Si un filtre est mal placé, montre la version corrigée.
[coller ta requête]
where-vs-having-erreur-agregations · 19
Checklist à appliquer avant de soumettre une requête
Pour chaque filtre de ta requête :
□ Ce filtre porte sur une colonne brute (pas calculée) → WHERE
□ Ce filtre porte sur COUNT(), SUM(), AVG(), MIN(), MAX() → HAVING
□ Ce filtre porte sur un alias du SELECT → HAVING ou CTE
□ J'ai vérifié qu'aucun agrégat n'est dans le WHERE
□ J'ai vérifié qu'aucune colonne brute n'est dans le HAVING par erreur
□ Les alias du SELECT ne sont pas référencés dans WHERE (non portable)
where-vs-having-erreur-agregations · 20
Récapitulatif — WHERE vs HAVING en une page
WHERE
HAVING
S'exécute
Avant GROUP BY
Après GROUP BY
Voit
Les lignes brutes
Les groupes agrégés
Accepte
Colonnes, expressions, sous-requêtes
Fonctions d'agrégation
N'accepte pas
COUNT(), SUM(), AVG()...
—
Usage typique
Filtrer par statut, date, pays...
Filtrer par total, moyenne, count...
Impact si mal placé
Erreur SQL (agrégat) ou résultat faux (lignes exclues avant agrégation)
Résultat faux (colonnes non agrégées dans HAVING)
✅ Checklist finale
☐ Je comprends que WHERE s'exécute avant GROUP BY et HAVING après
☐ Je n'utilise jamais COUNT(), SUM(), AVG() dans un WHERE
☐ Je n'utilise jamais une colonne brute dans un HAVING par erreur
☐ Je répète l'expression dans HAVING plutôt que d'utiliser l'alias du SELECT
☐ Je sais combiner WHERE et HAVING dans la même requête avec intention
☐ Je peux expliquer pourquoi un filtre mal placé fausse le résultat
🚀 Pratiquer sur Modai Lab
WHERE vs HAVING est testé dans presque tous les entretiens data. La seule façon de ne plus jamais se tromper : pratiquer sur des cas réels avec du feedback immédiat.
_Guide offert suite au post LinkedIn · Entraînez-vous sur modai-lab.com/test-sql/ · Partagez librement ♻️_
Modai Lab
La théorie c’est bien. La pratique sur des cas concrets, c’est mieux.
Exerce-toi sur les cas SQL qu’on te posera en entretien, avec un coach IA qui review chaque requête comme un senior. Essai gratuit, sans carte bancaire.