Parcourez arbres et graphes avec WITH RECURSIVE, en maîtrisant la profondeur et la détection de cycles.
Ouvrir cette leçon dans KodokonUne CTE récursive se compose de deux parties reliées par UNION ALL : un terme d'ancrage qui fournit les lignes de départ, et un terme récursif qui référence la CTE elle-même. SQLite exécute l'ancrage une fois, puis applique le terme récursif en boucle sur les nouvelles lignes, jusqu'à ce qu'il n'en produise plus aucune. Créons une hiérarchie de managers pour l'illustrer.
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
manager_id INTEGER
);
INSERT INTO employees (id, name, manager_id)
VALUES
(1, 'Ada', NULL),
(2, 'Grace', 1),
(3, 'Alan', 2),
(4, 'Edsger', 2);Pour dérouler l'organigramme sous Ada, l'ancrage sélectionne la racine avec une profondeur 0, et le terme récursif joint chaque employé à son manager déjà présent dans la CTE, en incrémentant la profondeur. La colonne depth que vous calculez vous-même est le moyen le plus simple de mesurer les niveaux d'une hiérarchie.
WITH RECURSIVE chain(id, name, depth) AS (
SELECT id, name, 0
FROM employees
WHERE id = 1
UNION ALL
SELECT e.id, e.name, c.depth + 1
FROM employees e
JOIN chain c ON e.manager_id = c.id
)
SELECT id, name, depth FROM chain;Un graphe se modélise par une table d'arêtes (src, dst). Le parcours suit la même mécanique, mais un graphe peut contenir des cycles : suivre 1 -> 2 -> 3 -> 1 boucle à l'infini. La parade consiste à mémoriser le chemin parcouru dans une colonne texte et à refuser tout nœud déjà visité. La fonction instr cherche un nœud entre deux points dans ce chemin.
CREATE TABLE edges (
src INTEGER NOT NULL,
dst INTEGER NOT NULL
);
INSERT INTO edges (src, dst) VALUES
(1, 2), (2, 3), (3, 1), (2, 4);
WITH RECURSIVE walk(node, path) AS (
SELECT 1, '.1.'
UNION ALL
SELECT e.dst,
w.path || e.dst || '.'
FROM edges e
JOIN walk w ON e.src = w.node
WHERE instr(w.path, '.' || e.dst || '.') = 0
)
SELECT node, path FROM walk;UNION ALL ?