Guide pratique · E-commerce · SaaS · Finance · RH · Lecture : ~20 min Teste ton niveau sur modai-lab.com/test-sql/
Pourquoi ce guide existe
Tout le monde connaît SUM(), AVG(), COUNT(). Presque personne ne maîtrise LAG() et LEAD().
Et pourtant c'est ce qu'on te demande en entretien senior.
Ce que la plupart font sans LAG() et LEAD() : trois sous-requêtes imbriquées, une jointure sur elle-même, une requête illisible que personne ne veut maintenir.
Ce que tu fais avec : une fenêtre. Une ligne. Un résultat propre.
Ce guide couvre :
La syntaxe complète avec les paramètres optionnels
5 cas concrets : e-commerce, SaaS, finance, RH, trafic web
Les erreurs classiques et comment les éviter
Un prompt Claude pour générer tes propres exercices
🧪 Calibre ton niveau avant de commencer
Sais-tu déjà expliquer ce que fait LAG(col, 2, 0) exactement ? Fais le test en 5 minutes et reçois ton score instantanément.
LAG(score_moyen_1an) OVER (ORDERBY cohorte) AS score_cohorte_prec,
LAG(taux_retention_pct) OVER (ORDERBY cohorte) AS retention_cohorte_prec,
LAG(salaire_moyen) OVER (ORDERBY cohorte) AS salaire_cohorte_prec,
LAG(nb_recrues) OVER (ORDERBY cohorte) AS recrues_cohorte_prec
FROM performance_cohorte
)
SELECT
TO_CHAR(cohorte, '"Q"Q YYYY') AS periode,
nb_recrues,
ROUND(score_moyen_1an, ) AS score_moyen,
ROUND(score_moyen_1an - COALESCE(score_cohorte_prec, score_moyen_1an), ) AS delta_score,
taux_retention_pct AS retention_pct,
ROUND(taux_retention_pct - COALESCE(retention_cohorte_prec, taux_retention_pct), ) AS delta_retention_pts,
ROUND(salaire_moyen, ) AS salaire_moyen,
CASE
WHEN score_moyen_1an > score_cohorte_prec AND taux_retention_pct > retention_cohorte_prec
THEN'✅ Meilleure cohorte'
WHEN score_moyen_1an < score_cohorte_prec AND taux_retention_pct < retention_cohorte_prec
THEN'⚠️ Cohorte en régression'
ELSE'→ Mitigé'
ENDAS evaluation
FROM avec_comparaison
ORDERBY cohorte;
lag-lead-fonctions-sql · 12
🧪 Teste LAG et LEAD sur des données réelles
Ces 5 cas sont exactement ce qu'on teste en entretien data senior. Modai Lab te soumet des datasets réels avec des séries temporelles — score immédiat.
LAG(ca) OVER (PARTITION BY pays) AS ca_precedent -- quel ordre ?
FROM revenus;
-- Le résultat dépend de l'ordre physique des lignes → non reproductible
-- ✅ ORDER BY toujours présent dans une window function avec LAG/LEAD
SELECT
mois,
ca,
LAG(ca) OVER (PARTITION BY pays ORDERBY mois) AS ca_precedent
FROM revenus;
lag-lead-fonctions-sql · 13
Erreur 2 — Division par NULL sur la première ligne
-- ❌ La première ligne a LAG() = NULL → division par NULL → NULL silencieux
SELECT
mois,
ca,
ROUND(. * (ca - LAG(ca) OVER (ORDERBY mois)) / LAG(ca) OVER (ORDERBY mois), ) AS pct
FROM revenus;
-- La première ligne retourne NULL pour pct — pas d'erreur, juste une donnée manquante
-- ✅ Option 1 : NULLIF pour éviter la division par zéro ET gérer les NULL
SELECT
mois,
ca,
ROUND(. * (ca - LAG(ca) OVER (ORDERBY mois))
/ NULLIF(LAG(ca) OVER (ORDERBY mois), ), ) AS pct
FROM revenus;
-- La première ligne retourne toujours NULL — c'est le comportement attendu
-- ✅ Option 2 : valeur par défaut avec le 3ème paramètre de LAG
SELECT
mois,
ca,
LAG(ca, , ca) OVER (ORDERBY mois) AS ca_precedent_ou_courant
-- Si première ligne : LAG retourne ca lui-même → variation = 0%
FROM revenus;
lag-lead-fonctions-sql · 14
Erreur 3 — Confondre PARTITION BY et ORDER BY
-- PARTITION BY : définit les groupes (repart de zéro pour chaque groupe)
-- ORDER BY : définit l'ordre dans lequel LAG/LEAD navigue
-- ❌ Erreur : ORDER BY avec la mauvaise colonne
SELECT
user_id,
event_type,
created_at,
LAG(event_type) OVER (PARTITION BY user_id ORDERBY event_type) AS prec
-- ORDER BY event_type = ordre alphabétique des types d'événements
-- Pas l'ordre chronologique → résultat faux pour l'analyse de funnel
FROM user_events;
-- ✅ Toujours ORDER BY sur la colonne temporelle pour les séries chronologiques
SELECT
user_id,
event_type,
created_at,
LAG(event_type) OVER (PARTITION BY user_id ORDERBY created_at) AS event_precedent
FROM user_events;
lag-lead-fonctions-sql · 15
Erreur 4 — Utiliser LAG dans un WHERE (impossible)
-- ❌ Impossible : les window functions ne peuvent pas être dans WHERE
SELECT mois, ca
FROM revenus
WHERE LAG(ca) OVER (ORDERBY mois) < ca;
-- Erreur SQL : window functions not allowed in WHERE
-- ✅ Envelopper dans une sous-requête ou une CTE
WITH avec_lag AS (
SELECT
mois,
ca,
LAG(ca) OVER (ORDERBY mois) AS ca_precedent
FROM revenus
)
SELECT mois, ca, ca_precedent
FROM avec_lag
WHERE ca > ca_precedent -- maintenant on peut filtrer
AND ca_precedent ISNOTNULL;
lag-lead-fonctions-sql · 16
Erreur 5 — Réutiliser LAG() plusieurs fois au lieu d'une CTE
-- ❌ Performance : LAG() calculé 4 fois sur la même fenêtre
SELECT
mois,
ca,
ca - LAG(ca) OVER (ORDERBY mois) AS variation,
ca / NULLIF(LAG(ca) OVER (ORDERBY mois), ) AS ratio,
CASEWHEN ca > LAG(ca) OVER (ORDERBY mois) THEN'Hausse'ELSE'Baisse'ENDAS tendance,
ca - LAG(ca, ) OVER (ORDERBY mois) AS vs_annee
FROM revenus;
-- Le moteur calcule LAG() 4 fois sur la même colonne
-- ✅ CTE pour calculer une fois, réutiliser partout
WITH avec_references AS (
SELECT
mois,
ca,
LAG(ca, , ) OVER (ORDERBY mois) AS ca_m1,
LAG(ca, , ) OVER (ORDERBY mois) AS ca_n1
FROM revenus
)
SELECT
mois,
ca,
ca - ca_m1 AS variation_absolue,
ROUND(. * (ca - ca_m1) / NULLIF(ca_m1, ), ) AS variation_pct,
CASEWHEN ca > ca_m1 THEN'Hausse'ELSE'Baisse'ENDAS tendance,
ca - ca_n1 AS vs_annee_precedente
FROM avec_references;
lag-lead-fonctions-sql · 17
🧪 Teste les erreurs classiques sur Modai Lab
Oublier ORDER BY, diviser par NULL, filtrer sur une window function : ces 5 erreurs sont exactement celles que Modai Lab détecte et explique dans son feedback.
2. Le schéma de la table concernée (4-5 colonnes, types inclus)
3. Un jeu de données d'exemple (5-8 lignes)
4. La question métier posée en français
5. La requête correcte avec commentaires sur chaque clause OVER()
6. Le résultat attendu (3-4 lignes exemple)
7. Une question de relance légèrement plus difficile
Progression :
- Exercice 1 : LAG simple avec variation M/M
- Exercice 2 : LAG avec PARTITION BY (plusieurs groupes)
- Exercice 3 : LAG avec offset > 1 (comparaison N-12 pour données mensuelles)
- Exercice 4 : LEAD pour détecter ce qui vient après
- Exercice 5 : Combinaison LAG + LEAD + CTE pour un cas avancé
Inclure les erreurs classiques à éviter pour chaque exercice.
lag-lead-fonctions-sql · 22
Prompt d'audit de tes requêtes existantes
Audite cette requête SQL qui utilise LAG() ou LEAD() :
[coller ta requête]
Vérifie :
1. ORDER BY présent dans chaque clause OVER() ?
2. Gestion des NULL sur la première/dernière ligne (NULLIF, valeur par défaut) ?
3. PARTITION BY correct pour les groupes ?
4. Les window functions sont-elles dans une CTE plutôt qu'en WHERE ?
5. Y a-t-il des répétitions inutiles de la même window function ?
Si des problèmes sont trouvés : montrer la version corrigée avec explications.
lag-lead-fonctions-sql · 23
Prompt "Remplace mes sous-requêtes par LAG/LEAD"
Cette requête utilise des sous-requêtes ou des self-joins pour comparer
des valeurs dans le temps. Réécris-la avec LAG() ou LEAD().
REQUÊTE ORIGINALE :
[coller ta requête avec les sous-requêtes imbriquées]
Objectif : obtenir le même résultat avec une syntaxe plus lisible et plus performante.
Explique chaque paramètre de la clause OVER() que tu utilises.
lag-lead-fonctions-sql · 24
Récapitulatif — LAG() et LEAD() en une page
Paramètre
Rôle
Exemple
expression
Colonne à récupérer
LAG(montant)
offset
Nombre de lignes en arrière/avant
LAG(montant, 3) → 3 lignes en arrière
default_value
Valeur si ligne inexistante
LAG(montant, 1, 0) → 0 si première ligne
PARTITION BY
Groupes séparés
Repart à NULL pour chaque groupe
ORDER BY
Ordre de navigation
Toujours obligatoire pour LAG/LEAD
Les 5 cas d'usage principaux :
Cas
Fonction
Paramètre clé
Variation M/M
LAG(ca, 1)
offset = 1
Comparaison N-1
LAG(ca, 12)
offset = 12 (données mensuelles)
Délai entre événements
LAG(date) avec soustraction
PARTITION BY user_id
Chute brutale
LAG(trafic) + CASE WHEN seuil
Seuil de % calculé
Prochain statut
LEAD(statut)
Pour les transitions
✅ Checklist entretien — LAG() et LEAD()
☐ Je sais expliquer la différence entre LAG() et LEAD()
☐ Je sais utiliser les 3 paramètres : expression, offset, default_value
☐ Je sais toujours mettre ORDER BY dans la clause OVER()
☐ Je sais utiliser PARTITION BY pour comparer dans des groupes séparés
☐ Je sais que LAG() ne peut pas être dans un WHERE → je passe par une CTE
☐ Je sais gérer les NULL de la première ligne avec NULLIF() ou la valeur par défaut
☐ Je peux réécrire une sous-requête corrélée de comparaison temporelle avec LAG()
🚀 Pratiquer sur Modai Lab
LAG() et LEAD() sont les fonctions qui distinguent les analysts juniors des seniors en entretien. La seule façon de les maîtriser vraiment : pratiquer sur des séries temporelles réelles 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.