Niveau 20 : Requêtes récursives : WITH RECURSIVE
Mis à jour le
Pro · niveau 20 sur 20. Objectif : Générer des séries et parcourir des hiérarchies de profondeur inconnue.
Notions : WITH RECURSIVE cas de départ étape récursive hiérarchies séries
Leçon
Une CTE récursive est une CTE qui se lit elle-même. Elle sert à deux choses que les requêtes ordinaires ne savent pas faire : générer une série de valeurs qui n'existe dans aucune table, et parcourir une hiérarchie dont on ne connaît pas la profondeur.
Elle a deux parties reliées par UNION ALL. Le cas de départ est un SELECT ordinaire qui produit les premières lignes. L'étape récursive est un SELECT qui lit la CTE elle-même et fabrique de nouvelles lignes à partir de celles produites au tour précédent.
SQL déroule le calcul tour par tour. Dans l'exemple, le départ produit x = 1. Au tour 1, l'étape lit 1 et produit 2 ; au tour 2, elle lit 2 et produit 3, et ainsi de suite jusqu'à 5. Au tour suivant, la condition x < 5 est fausse pour 5 : l'étape ne produit plus rien et le calcul s'arrête. Le résultat réunit toutes les lignes produites : 1, 2, 3, 4, 5. Le WHERE de l'étape récursive est donc la condition d'arrêt.
Usage 1, les séries. Avec date(day, '+1 day') ou strftime('%Y-%m', month || '-01', '+1 month'), vus au niveau 6, on génère tous les jours ou tous les mois d'une période. Un LEFT JOIN y rattache ensuite les données : les mois sans activité apparaissent avec 0.
Usage 2, les hiérarchies. Le départ sélectionne la racine, par exemple l'employée sans manager (Alice, profondeur 0). Chaque tour joint staff à la CTE pour trouver les subordonnés des personnes trouvées au tour précédent : Bob, Claire et David au tour 1, leurs équipes au tour 2. Le calcul s'arrête quand plus personne n'a de subordonné.
Si les données contiennent un cycle (A manager de B, B manager de A), la requête tourne sans fin. Deux protections existent. La plus sûre : une limite de profondeur dans l'étape récursive, par exemple WHERE depth < 20. L'autre : relier le départ et l'étape par UNION au lieu de UNION ALL ; une ligne déjà produite n'est alors pas reproduite, et la boucle s'arrête quand le cycle revient sur une ligne identique. Attention : si la ligne contient un compteur comme depth, elle est toujours nouvelle et UNION ne suffit plus.
Comme toute requête, une CTE récursive ne garantit pas l'ordre des lignes : ajoute ORDER BY dans la requête finale dès que l'ordre compte.
Syntaxe
WITH RECURSIVE t(x) AS (
SELECT départ
UNION ALL
SELECT x + 1
FROM t
WHERE x < fin
)
SELECT x
FROM t;Exemple commenté
WITH RECURSIVE n(x) AS (
SELECT 1
UNION ALL
SELECT x + 1
FROM n
WHERE x < 5
)
SELECT x
FROM n;Départ : 1. Chaque tour ajoute x + 1 tant que x < 5. Résultat : 1, 2, 3, 4, 5.
Résultat de l’exemple
| x |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
À retenir
- Départ UNION ALL étape récursive.
- L'étape récursive lit la CTE elle-même.
- Le WHERE de l'étape récursive arrête la boucle.
Pièges fréquents
- Oublier la condition d'arrêt : la requête tourne sans fin.
- Le nombre de colonnes du départ et de l'étape récursive doit être le même.
Les 5 exercices du niveau
- Affiche les nombres de 1 à 10 dans une colonne x.
- Affiche tous les jours du 1er au 7 juillet 2025 dans une colonne day.
- Affiche le nom de toutes les personnes qui travaillent sous la responsabilité de Bob (id 2), directement ou indirectement.
- Affiche chaque employé avec sa profondeur dans l'organigramme (depth) : 0 pour la personne sans manager, 1 pour ses subordonnés directs, etc.
- Affiche le nombre de prêts de chaque mois de janvier à juin 2025 (format AAAA-MM), y compris les mois sans aucun prêt, dans l'ordre chronologique.
Dans SpeedQL, chaque requête est corrigée tout de suite : le résultat est comparé à celui attendu, puis la requête est relancée sur une base de contrôle cachée. Chaque exercice a ses indices écrits, à afficher seulement si tu bloques.
Voir aussi : la fiche de l’aide-mémoire · les exercices SQL corrigés sur cette notion
Faire les exercices du niveau 20
Gratuit, sans inscription : la leçon et les 5 exercices s’ouvrent directement dans ton navigateur.
← Niveau précédent : Fonctions de fenêtre : LAG, LEAD et cadres