Guide pratique · SQL · Excel · Power BI · Lecture : ~15 min Teste ton niveau sur modai-lab.com/test-sql/
Pourquoi ce guide existe NULL nâest pas zĂ©ro. Ce nâest pas une virgule oubliĂ©e. Câest une valeur inconnue â et SQL la traite diffĂ©remment dâun zĂ©ro Ă chaque opĂ©ration, sans jamais te prĂ©venir.
SUM() ignore les NULL silencieusement. Il calcule⊠en oubliant des lignes. Tes totaux sont faux. Tes KPIs aussi. Et ton rapport du lundi matin avec.
Une rĂšgle simple Ă retenir :
Si tu ne forces pas la valeur, tu ne contrÎles pas le résultat.
Ce guide couvre :
9 cas concrets NULL vs zéro en SQL, Excel et Power BI
Les formules correctes pour chaque situation
Les piÚges COUNT(), AVG() et GROUP BY liés à NULL
La checklist dâaudit pour tes modĂšles existants
La distinction fondamentale Valeur
Signification
Exemple métier
NULL
Valeur inconnue ou absente
Chiffre dâaffaires dâun client qui nâa pas encore commandĂ©
0
Valeur connue , qui vaut zéro
Chiffre dâaffaires dâun client qui a commandĂ© pour 0⏠(remboursĂ©)
'' (chaĂźne vide)
Valeur connue , chaĂźne vide
Commentaire laissé intentionnellement vide
Traiter NULL comme un zĂ©ro, câest confondre âon ne sait pasâ avec âon sait que câest nulâ. Ce sont deux rĂ©alitĂ©s mĂ©tier complĂštement diffĂ©rentes.
đ§Ș Teste ton niveau avant de commencer Sais-tu dĂ©jĂ comment SQL traite NULL dans SUM(), AVG() et GROUP BY ? Fais le test en direct et reçois ton score instantanĂ©ment. đ Faire le test sur modai-lab.com/test-sql/ Exercices interactifs · RĂ©sultat en direct · Parcours personnalisĂ© selon ton niveau
PARTIE 1 â Les 9 cas concrets NULL vs ZĂ©ro Cas 1 â SUM() ignore les NULL sans prĂ©venir Câest le cas le plus frĂ©quent et le plus dangereux.
-- Données
-- user_id | montant
-- 1 | 100
-- 2 | NULL â commande sans montant renseignĂ©
-- 3 | 50
-- 4 | NULL
Â
-- â Ce que tu crois calculer : 100 + 0 + 50 + 0 = 150
-- â
Ce que SUM() retourne réellement : 100 + 50 = 150
SELECT SUM (montant) FROM orders;
-- RĂ©sultat : 150 â mais tu ne sais pas si 2 lignes ont Ă©tĂ© ignorĂ©es
null-vs-zero-piege-kpis · 01 Le problÚme : le résultat est identique que les NULL valent 0 ou 10 000. Tu ne peux pas distinguer les deux cas sans vérification explicite.
-- â
Diagnostic : combien de lignes sont ignorées ?
SELECT
COUNT (*) AS total_lignes,
COUNT (montant) AS lignes_avec_valeur,
COUNT (*) - COUNT (montant) AS lignes_null,
SUM (montant) AS somme_sans_null,
SUM (COALESCE (montant, )) AS somme_avec_null_a_zero
FROM orders;
null-vs-zero-piege-kpis · 02 -- â
Forcer le comportement selon l'intention métier
-- Intention : NULL = données manquantes, ne pas inclure
SELECT SUM (montant) FROM orders; -- comportement par défaut
Â
-- Intention : NULL = 0, inclure dans la somme
SELECT SUM (COALESCE (montant, )) FROM orders;
null-vs-zero-piege-kpis · 03 đĄ La bonne question Ă se poser : NULL signifie-t-il âon ne sait pasâ ou âça vaut zĂ©roâ dans ce contexte mĂ©tier ? La rĂ©ponse dĂ©termine si tu utilises SUM() brut ou SUM(COALESCE(..., 0)).
Cas 2 â AVG() : la moyenne trompeuse AVG() ignore aussi les NULL â ce qui change radicalement la moyenne calculĂ©e.
-- Données : notes d'évaluation
-- user_id | note
-- 1 | 8
-- 2 | NULL â pas encore Ă©valuĂ©
-- 3 | 6
-- 4 | NULL
-- 5 | 10
Â
-- â AVG() calcule (8 + 6 + 10) / 3 = 8.0
-- Ce n'est pas la moyenne de ton équipe, c'est la moyenne des évalués
SELECT AVG (note) FROM evaluations; -- retourne 8.0
Â
-- â
Si NULL doit compter comme 0 (non-évalué = mauvais score)
SELECT AVG (COALESCE (note, )) FROM evaluations; -- retourne (8+0+6+0+10)/5 = 4.8
null-vs-zero-piege-kpis · 04 Ăcart dans cet exemple : 8.0 vs 4.8. Ton rapport de performance affiche le double de la rĂ©alitĂ© si tu nâas pas tranchĂ© cette question.
Cas 3 â COUNT(*) vs COUNT(colonne) Confusion classique en entretien data.
-- COUNT(*) : compte TOUTES les lignes, NULL compris
SELECT COUNT (*) FROM orders; -- retourne 4
Â
-- COUNT(colonne) : compte les lignes oĂč la colonne est NOT NULL
SELECT COUNT (montant) FROM orders; -- retourne 2 (les NULL sont exclus)
Â
-- COUNT(DISTINCT colonne) : valeurs distinctes non-NULL
SELECT COUNT (DISTINCT montant) FROM orders; -- retourne 2 (100 et 50)
null-vs-zero-piege-kpis · 05 -- â
Comparaison diagnostic
SELECT
COUNT (*) AS toutes_les_lignes,
COUNT (montant) AS lignes_renseignees,
COUNT (*) - COUNT (montant) AS lignes_null,
ROUND(. * (COUNT (*) - COUNT (montant)) / COUNT (*), ) AS pct_null
FROM orders;
null-vs-zero-piege-kpis · 06 Cas 4 â NULL dans GROUP BY GROUP BY crĂ©e un groupe Ă part pour les NULL. Ce comportement surprend souvent.
-- Données
-- region | montant
-- 'Nord' | 100
-- 'Sud' | 200
-- NULL | 150 â rĂ©gion non renseignĂ©e
-- 'Nord' | 80
Â
SELECT region, SUM (montant) AS ca
FROM orders
GROUP BY region;
null-vs-zero-piege-kpis · 07 region
ca
Nord
180
Sud
200
NULL
150
-- â
Nommer explicitement le groupe NULL
SELECT
COALESCE (region, 'Non renseignée' ) AS region,
SUM (montant) AS ca
FROM orders
GROUP BY region;
null-vs-zero-piege-kpis · 08 â ïž Si tu fais un HAVING SUM(montant) > 100, le groupe NULL sera aussi filtrĂ©. Assure-toi que câest lâintention.
Cas 5 â NULL dans les comparaisons et le WHERE NULL ne peut jamais ĂȘtre Ă©gal Ă quoi que ce soit â pas mĂȘme Ă lui-mĂȘme.
-- â Ces filtres retournent 0 rĂ©sultat si la valeur est NULL
SELECT * FROM users WHERE region = NULL ;
SELECT * FROM users WHERE region != 'Nord' ; -- exclut aussi les NULL !
SELECT * FROM users WHERE region IN ('Nord' , 'Sud' ); -- exclut les NULL
Â
-- â
Tester NULL explicitement
SELECT * FROM users WHERE region IS NULL ;
SELECT * FROM users WHERE region IS NOT NULL ;
Â
-- â
Inclure les NULL dans un filtre
SELECT * FROM users WHERE region != 'Nord' OR region IS NULL ;
null-vs-zero-piege-kpis · 09 -- PiÚge classique : NOT IN avec NULL dans la liste
SELECT * FROM users
WHERE region NOT IN ('Nord' , NULL ); -- retourne toujours 0 lignes !
-- Car "region != NULL" est toujours UNKNOWN
Â
-- â
Bonne pratique
SELECT * FROM users
WHERE region NOT IN (SELECT region FROM exclusions WHERE region IS NOT NULL );
null-vs-zero-piege-kpis · 10 Cas 6 â NULL dans les calculs arithmĂ©tiques Toute opĂ©ration arithmĂ©tique avec NULL retourne NULL.
-- Données
-- prix = 100, remise = NULL
Â
-- â RĂ©sultat NULL, pas 100
SELECT prix - remise AS prix_final FROM produits; -- retourne NULL
Â
-- â
Forcer une valeur par défaut
SELECT prix - COALESCE (remise, ) AS prix_final FROM produits; -- retourne 100
null-vs-zero-piege-kpis · 11 -- Cas concret : calcul de marge avec des coûts parfois inconnus
SELECT
produit,
prix_vente,
cout_production,
prix_vente - COALESCE (cout_production, ) AS marge_mini,
CASE
WHEN cout_production IS NULL THEN 'CoĂ»t inconnu â marge non calculable'
ELSE CAST (prix_vente - cout_production AS VARCHAR )
END AS marge_avec_alerte
FROM produits;
null-vs-zero-piege-kpis · 12 Cas 7 â NULL et les fonctions de fenĂȘtre LAG(), LEAD(), FIRST_VALUE() retournent NULL quand il nây a pas de valeur prĂ©cĂ©dente/suivante â et câest un NULL lĂ©gitime. Mais ça peut se mĂ©langer avec les NULL de donnĂ©es.
SELECT
user_id,
mois,
ca,
LAG(ca) OVER (PARTITION BY user_id ORDER BY mois) AS ca_mois_prec,
-- Distinguer NULL de LAG (premiÚre ligne) vs NULL de données
CASE
WHEN LAG(ca) OVER (PARTITION BY user_id ORDER BY mois) IS NULL
AND ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY mois) =
THEN 'PremiÚre période'
WHEN LAG(ca) OVER (PARTITION BY user_id ORDER BY mois) IS NULL
THEN 'Donnée manquante'
ELSE 'OK'
END AS statut_precedent
FROM revenus_mensuels;
null-vs-zero-piege-kpis · 13 Cas 8 â NULL dans les jointures Deux NULL ne sont jamais Ă©gaux dans une jointure â les lignes NULL ne se joignent pas.
-- â Deux tables avec des clĂ©s NULL ne jointurent pas entre elles
SELECT a.id, b.valeur
FROM table_a a
JOIN table_b b ON a.cle = b.cle;
-- Les lignes oĂč a.cle IS NULL ou b.cle IS NULL sont exclues du rĂ©sultat
Â
-- â
Si tu veux joindre les NULL aussi
SELECT a.id, b.valeur
FROM table_a a
JOIN table_b b ON a.cle IS NOT DISTINCT FROM b.cle;
-- IS NOT DISTINCT FROM = equality qui traite NULL = NULL comme TRUE
null-vs-zero-piege-kpis · 14 Cas 9 â NULL dans CASE WHEN Lâordre des conditions dans un CASE WHEN peut masquer ou exposer les NULL.
-- â NULL tombe dans ELSE sans avertissement
SELECT
montant,
CASE
WHEN montant > THEN 'ĂlevĂ©'
WHEN montant <= THEN 'Faible'
ELSE 'Inconnu' -- NULL atterrit ici silencieusement
END AS segment
FROM orders;
Â
-- â
Tester NULL explicitement en premier
SELECT
montant,
CASE
WHEN montant IS NULL THEN 'Donnée manquante'
WHEN montant > THEN 'ĂlevĂ©'
ELSE 'Faible'
END AS segment
FROM orders;
null-vs-zero-piege-kpis · 15 đ§Ș Teste tes rĂ©flexes NULL en conditions rĂ©elles Tu viens de lire les 9 cas. Maintenant : est-ce que tu les repĂšres dans une vraie requĂȘte ? Modai Lab te soumet des requĂȘtes Ă dĂ©boguer â avec un rĂ©sultat attendu et un score immĂ©diat. đ Tester mes rĂ©flexes sur modai-lab.com/test-sql/ Score immĂ©diat · Explication de chaque erreur · Niveau calibrĂ© automatiquement
PARTIE 2 â NULL en Excel et Power BI Excel â Les Ă©quivalents des piĂšges SQL Comportement SQL
Ăquivalent Excel
PiĂšge
SUM() ignore NULL
SOMME() ignore les cellules vides
Cellule vide â cellule Ă 0
AVG() ignore NULL
MOYENNE() ignore les cellules vides
Dénominateur réduit silencieusement
COUNT(colonne)
NB()
Ne compte pas les cellules vides
COUNT(*)
NBVAL() + NB.VIDE()
Vérifier les deux
COALESCE(col, 0)
SI(ESTVIDE(A1), 0, A1)
Ă appliquer avant tout calcul
Formules Excel pour gérer les vides :
// Remplacer les cellules vides par 0 avant SOMME
=SOMME(SI(ESTVIDE(A1:A10), 0, A1:A10))
Â
// Compter les cellules vides
=NB.VIDE(A1:A10)
Â
// Moyenne en incluant les vides comme 0
=SOMME(SI(ESTVIDE(A1:A10), 0, A1:A10)) / NBVAL(A1:A10) + NB.VIDE(A1:A10))
Â
// SIERREUR pour les divisions par zéro liées aux NULL
=SIERREUR(B1/C1, "N/A")
null-vs-zero-piege-kpis · 16 · Formules Excel pour gĂ©rer les vides : Power BI / DAX â NULL se nomme BLANK() Dans DAX (Power BI), NULL sâappelle BLANK(). Le comportement est similaire Ă SQL mais les fonctions diffĂšrent.
// BLANK() dans DAX
Ventes Total = SUM(Commandes[Montant])
// Ignore les BLANK() â mĂȘme comportement que SUM() en SQL
Â
// Forcer BLANK() Ă 0
Ventes Total Zero = SUMX(Commandes, IF(ISBLANK(Commandes[Montant]), 0, Commandes[Montant]))
Â
// Tester si une valeur est BLANK
Statut = IF(ISBLANK([CA]), "Donnée manquante", "OK")
Â
// COALESCE équivalent en DAX
Valeur = COALESCE([Montant], 0)
// ou
Valeur = IF(ISBLANK([Montant]), 0, [Montant])
null-vs-zero-piege-kpis · 17 PiÚge Power BI fréquent :
// â Une mesure avec BLANK() dans un visuel
// Power BI filtre automatiquement les lignes BLANK
// â certains clients disparaissent du tableau
Â
// â
Forcer l'affichage avec +0
Clients avec zero = [Clients actifs] + 0
// Le +0 convertit BLANK en 0 et force l'affichage
null-vs-zero-piege-kpis · 18 · PiĂšge Power BI frĂ©quent : đ§Ș Test intermĂ©diaire â NULL en SQL et dans tes outils BI Les piĂšges NULL touchent SQL, Excel et Power BI. Savoir les dĂ©tecter dans les trois contextes, câest ce qui distingue un analyste junior dâun analyste senior. đ Pratiquer sur modai-lab.com/test-sql/ ScĂ©narios data rĂ©els · Feedback ligne par ligne · Progression mesurĂ©e
PARTIE 3 â Les piĂšges COUNT, AVG et GROUP BY RĂ©cap des comportements NULL par fonction Fonction SQL
Comportement avec NULL
Ce quâil faut faire
SUM(col)
Ignore les NULL
SUM(COALESCE(col, 0)) si NULL = 0
AVG(col)
Ignore les NULL (dénominateur réduit)
Décider si NULL = 0 ou exclu
COUNT(col)
Ignore les NULL
COUNT(*) si tu veux tout compter
COUNT(*)
Compte tout, NULL inclus
Comportement correct par défaut
MIN(col)
Ignore les NULL
Attention si toutes les valeurs sont NULL â retourne NULL
MAX(col)
Ignore les NULL
Idem
GROUP BY col
Crée un groupe NULL séparé
COALESCE(col, 'Inconnu') dans le GROUP BY
HAVING SUM(col)
Exclut les groupes de NULL
Comportement souvent non voulu
ORDER BY col
NULL en premier (ASC) ou dernier (DESC) selon le SGBD
NULLS LAST ou NULLS FIRST
PiĂšge AVG â Le dĂ©nominateur fantĂŽme -- Contexte : notes de satisfaction client (1 Ă 10)
-- 40% des clients n'ont pas rĂ©pondu â NULL
Â
-- â AVG() exclut les non-rĂ©pondants
SELECT AVG (note_satisfaction) AS satisfaction_moyenne
FROM enquetes;
-- RĂ©sultat : 7.8 â mais calculĂ© sur 60% des clients seulement
Â
-- â
Version qui expose le vrai dénominateur
SELECT
AVG (note_satisfaction) AS moy_repondants,
AVG (COALESCE (note_satisfaction, )) AS moy_avec_neutre_pour_nr,
COUNT (*) AS total_clients,
COUNT (note_satisfaction) AS clients_ayant_repondu,
ROUND(. * COUNT (note_satisfaction) / COUNT (*), ) AS taux_reponse_pct
FROM enquetes;
null-vs-zero-piege-kpis · 19 PiÚge GROUP BY + ORDER BY NULL -- PostgreSQL : NULL en dernier dans ORDER BY ASC (comportement par défaut)
SELECT region, SUM (ca)
FROM ventes
GROUP BY region
ORDER BY SUM (ca) DESC NULLS LAST; -- forcer NULL Ă la fin
Â
-- MySQL : NULL en premier dans ORDER BY ASC
-- SQL Server : NULL en premier dans ORDER BY ASC
-- Comportement différent selon le SGBD !
Â
-- â
Toujours ĂȘtre explicite
ORDER BY SUM (ca) DESC NULLS LAST
-- ou
ORDER BY SUM (ca) DESC NULLS FIRST
null-vs-zero-piege-kpis · 20 PiĂšge HAVING avec NULL -- â Le groupe NULL peut ĂȘtre inclus ou exclu selon la condition
SELECT region, COUNT (*) AS nb_clients
FROM users
GROUP BY region
HAVING COUNT (*) > ;
-- Le groupe region = NULL est inclus si il a > 10 lignes
-- C'est rarement l'intention
Â
-- â
Exclure les NULL avant le GROUP BY si non voulu
SELECT region, COUNT (*) AS nb_clients
FROM users
WHERE region IS NOT NULL -- exclure en amont
GROUP BY region
HAVING COUNT (*) > ;
null-vs-zero-piege-kpis · 21 PiÚge STRING_AGG / LISTAGG avec NULL -- STRING_AGG ignore les NULL silencieusement
SELECT
order_id,
STRING_AGG(commentaire, ', ' ) AS tous_commentaires
FROM order_lines
GROUP BY order_id;
-- Les lignes sans commentaire sont ignorées sans avertissement
Â
-- â
Remplacer les NULL si nécessaire
SELECT
order_id,
STRING_AGG(COALESCE (commentaire, '[sans commentaire]' ), ', ' ) AS tous_commentaires
FROM order_lines
GROUP BY order_id;
null-vs-zero-piege-kpis · 22 đ§Ș Test avancĂ© â PiĂšges COUNT, AVG et GROUP BY Ces comportements sont exactement ce quâon teste en entretien data senior. Sur Modai Lab, des exercices reproduisent ces scĂ©narios avec des donnĂ©es rĂ©elles â dĂ©nominateur fantĂŽme, groupe NULL, ORDER BY surprise. đ Reproduire ces cas sur modai-lab.com/test-sql/ Mode entretien · Timer · Score et feedback dĂ©taillĂ©
PARTIE 4 â Checklist dâaudit pour tes modĂšles existants Utilise cette checklist pour auditer une requĂȘte ou un modĂšle dbt existant.
Ătape 1 â Inventorier les colonnes nullable -- PostgreSQL : lister les colonnes nullable de ta table
SELECT
column_name,
data_type,
is_nullable
FROM information_schema.columns
WHERE table_name = 'ta_table'
AND is_nullable = 'YES'
ORDER BY ordinal_position;
null-vs-zero-piege-kpis · 23 Ătape 2 â Mesurer le taux de NULL par colonne -- Audit de nullitĂ© sur toutes les colonnes clĂ©s
SELECT
COUNT (*) AS total,
COUNT (montant) AS montant_renseigné,
COUNT (*) - COUNT (montant) AS montant_null,
COUNT (region) AS region_renseignée,
COUNT (*) - COUNT (region) AS region_null,
COUNT (note) AS note_renseignée,
COUNT (*) - COUNT (note) AS note_null
FROM ta_table;
null-vs-zero-piege-kpis · 24 Ătape 3 â VĂ©rifier tes SUM() et AVG() critiques -- Pour chaque KPI calculĂ© avec SUM() ou AVG(), lancer ce diagnostic
SELECT
'KPI: CA Total' AS kpi,
SUM (montant) AS valeur_actuelle,
SUM (COALESCE (montant, )) AS valeur_si_null_egal_zero,
SUM (montant) - SUM (COALESCE (montant, )) AS ecart
FROM orders
UNION ALL
SELECT
'KPI: Note moyenne' AS kpi,
AVG (note),
AVG (COALESCE (note, )),
AVG (note) - AVG (COALESCE (note, ))
FROM evaluations;
-- Si ecart != 0 : ton KPI actuel ignore des données
null-vs-zero-piege-kpis · 25 Ătape 4 â VĂ©rifier les GROUP BY avec colonnes nullable -- Cherche les groupes NULL inattendus
SELECT region, COUNT (*) AS n
FROM users
GROUP BY region
ORDER BY region NULLS LAST;
-- Si tu vois NULL dans les résultats et que ce n'est pas voulu :
-- ajouter WHERE region IS NOT NULL ou COALESCE dans le GROUP BY
null-vs-zero-piege-kpis · 26 Ătape 5 â Scanner les CASE WHEN pour les NULL oubliĂ©s -- Template : toujours ajouter le cas NULL explicitement
SELECT
CASE
WHEN colonne IS NULL THEN 'Valeur manquante' -- â toujours en premier
WHEN colonne > THEN 'ĂlevĂ©'
WHEN colonne > THEN 'Faible'
ELSE 'Zéro ou négatif'
END AS segment
FROM ta_table;
null-vs-zero-piege-kpis · 27 đ§Ș Test final â Valide ton audit en conditions rĂ©elles Tu as les outils pour auditer tes modĂšles. La prochaine Ă©tape : les appliquer sous contrainte de temps sur un dataset inconnu â comme en entretien ou en production. đ Valider mes acquis sur modai-lab.com/test-sql/ Datasets rĂ©alistes · Avant/aprĂšs interactif · Validation automatique
đ RĂ©capitulatif â Les 9 cas NULL vs ZĂ©ro #
Cas
Fonction concernée
Impact
1
SUM() ignore les NULL
SUM()
Totaux sous-estimés
2
AVG() réduit le dénominateur
AVG()
Moyenne surévaluée
3
COUNT(*) vs COUNT(col)
COUNT()
Comptages incorrects
4
GROUP BY crée un groupe NULL
GROUP BY
Groupe fantĂŽme dans les rapports
5
!= et NOT IN excluent les NULL
WHERE
Lignes manquantes silencieuses
6
ArithmĂ©tique avec NULL â NULL
+, -, *, /
KPIs Ă NULL au lieu de valeur
7
LAG/LEAD retournent NULL légitime
Window functions
Confusion NULL données vs NULL structure
8
JOIN sur clés NULL
JOIN
Lignes non jointurées
9
CASE WHEN oublie NULL dans ELSE
CASE WHEN
Mauvais segment pour les NULL
â
Checklist rapide â Toutes mes SUM() sur colonnes nullable sont vĂ©rifiĂ©es â jâai dĂ©cidĂ© si NULL = 0 ou exclu
â Mes AVG() affichent le taux de rĂ©ponse Ă cĂŽtĂ© de la moyenne
â Jâutilise COUNT(*) vs COUNT(col) avec intention
â Mes GROUP BY sur colonnes nullable ont un COALESCE ou un WHERE IS NOT NULL
â Mes WHERE col != valeur incluent explicitement OR col IS NULL si nĂ©cessaire
â Mes CASE WHEN testent IS NULL en premier
â Mes calculs arithmĂ©tiques utilisent COALESCE(col, 0) sur les colonnes nullable
â Mes rapports Excel et Power BI distinguent cellule vide et cellule Ă zĂ©ro
â Jâai mesurĂ© le taux de NULL sur mes colonnes KPI clĂ©s
đ SâentraĂźner sur Modai Lab Lire ce guide, câest comprendre. Ăcrire les requĂȘtes soi-mĂȘme sous contrainte, câest retenir.
đ modai-lab.com â Exercices SQL data rĂ©els · Feedback immĂ©diat · Parcours entretien
Guide offert suite au post LinkedIn · EntraĂźnez-vous sur modai-lab.com/test-sql/ · Partagez librement â»ïž