Durchlaufe Bäume und Graphen mit WITH RECURSIVE und meistere Tiefe und Zyklenerkennung.
Diese Lektion in Kodokon öffnenEine rekursive CTE besteht aus zwei durch UNION ALL verbundenen Teilen: einem Anker-Term, der die Startzeilen liefert, und einem rekursiven Term, der die CTE selbst referenziert. SQLite führt den Anker einmal aus und wendet dann den rekursiven Term in einer Schleife auf die neuen Zeilen an, bis keine mehr entstehen. Erstellen wir eine Hierarchie von Vorgesetzten, um das zu veranschaulichen.
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);Um das Organigramm unter Ada zu entfalten, wählt der Anker die Wurzel mit einer Tiefe von 0, und der rekursive Term verbindet jeden Mitarbeiter mit seinem bereits in der CTE vorhandenen Vorgesetzten und erhöht dabei die Tiefe. Die Spalte depth, die du selbst berechnest, ist der einfachste Weg, die Ebenen einer Hierarchie zu messen.
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;Ein Graph wird durch eine Kantentabelle (src, dst) modelliert. Das Durchlaufen folgt derselben Mechanik, aber ein Graph kann Zyklen enthalten: 1 -> 2 -> 3 -> 1 zu folgen, dreht sich endlos im Kreis. Das Gegenmittel ist, sich den durchlaufenen Pfad in einer Textspalte zu merken und jeden bereits besuchten Knoten abzulehnen. Die Funktion instr sucht einen Knoten zwischen zwei Punkten innerhalb dieses Pfads.
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 eine unendliche Rekursion?