Direkt zum Hauptinhalt springen
eLearner.app
Modul 7 · Lektion 4 von 428/57 im Kurs~14 min
Lektionen des Moduls (4/4)

Rekursive CTEs: Hierarchien mit beliebiger Tiefe

Ein Self-JOIN (Modul 5) findet nur eine Ebene einer Hierarchie: Kind → Elternteil. Aber was passiert, wenn die Hierarchie 3, 5 oder n Ebenen tief ist? und Sie wissen nicht im Voraus, wie viele? Sie benötigen rekursive CTEs: a CTE, der sich auf sich selbst bezieht, um die Ergebnisse iterativ zu „erweitern“.

Im ecommerce-Datensatz hat die categories-Tabelle drei Wurzeln (Elettronica, Libri, Casa) und je 2 Kinder – ein 2-stöckiger Baum. Es ist ein einfacher Fall, aber genug, um das Muster zu lernen.

Die Syntax

SQL
WITH RECURSIVE nome (col1, col2, …) AS (
  -- (1) Termine BASE: le righe di partenza
  SELECT
  FROM
  WHERE

  UNION ALL

  -- (2) Termine RICORSIVO: si appoggia a "nome" stesso per espandere
  SELECT
  FROM   tabella  t
  JOIN   nome    n  ON
)
SELECT * FROM nome;

So funktioniert es in der Praxis:

  1. PostgreSQL führt den Basisterm einmal aus.
  2. Es führt den rekursiven Term unter Verwendung der soeben erzeugten Zeilen aus „Eingabe“ (nicht der gesamte CTE: nur das Inkrement).
  3. Schritt 2 wird wiederholt, bis der rekursive Term 0 neue Zeilen erzeugt.
  4. Das Endergebnis ist der UNION ALL aller Schritte.

Beispiel 1: Baum mit Tiefe und Pfad

SQL
WITH RECURSIVE tree AS (
  -- base: le radici (parent_id IS NULL)
  SELECT id,
         name,
         parent_id,
         1                 AS depth,
         name              AS path
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  -- ricorsivo: per ogni categoria che ha come parent una riga già in tree
  SELECT c.id,
         c.name,
         c.parent_id,
         t.depth + 1,
         t.path || ' > ' || c.name
  FROM   categories c
  JOIN   tree       t ON c.parent_id = t.id
)
SELECT id, name, depth, path
FROM   tree
ORDER BY path;

Die erste Iteration erzeugt 3 Zeilen (die Wurzeln auf Ebene 1). Der Zweite Iteration findet die 6 Kinder (Ebene 2). Die dritte Iteration findet nichts → erledigt.

Beispiel 2: Finden Sie bei einem gegebenen Knoten dessen Wurzel

Eine Variante „von oben nach unten → von unten nach oben“: Wir verbreiten die ID der Wurzel nach unten der Baum.

SQL
WITH RECURSIVE tree AS (
  SELECT id,
         name,
         parent_id,
         id   AS root_id,
         name AS root_name
  FROM   categories
  WHERE  parent_id IS NULL

  UNION ALL

  SELECT c.id,
         c.name,
         c.parent_id,
         t.root_id,    -- propago lo stesso id_radice
         t.root_name   -- e nome
  FROM   categories c
  JOIN   tree       t ON c.parent_id = t.id
)
SELECT id, name, root_name
FROM   tree
ORDER BY id;

Probieren Sie es aus

Übung#sql.m7.l4.e1
Versuche: 0Wird geladen…

Verwenden Sie einen rekursiven CTE namens „tree“, um die Kategoriehierarchie zu reduzieren. ID, Name, Tiefe (1 für Roots, 2 für Kinder usw.) und Pfad (z. B. „Elettronica > Audio“) anzeigen. Nach Pfad sortieren.

Editor wird geladen…
Hinweis anzeigen

Der JOIN im rekursiven Begriff verknüpft c.parent_id mit der bereits im Baum vorhandenen Zeile (t.id).

Lösung nach 3 Versuchen verfügbar

Wiederholungsübung

Übung#sql.m7.l4.e2
Versuche: 0Wird geladen…

Zeigen Sie für jede Kategorie die ID, den Namen und den Root-Namen an (den Namen der Root-Kategorie oben im Baum, zu der sie gehört). Wurzeln haben root_name = name. Nach ID bestellen.

Editor wird geladen…
Hinweis anzeigen

Geben Sie root_name vom übergeordneten Element (t.root_name) an das untergeordnete Element (c) weiter.

Lösung nach 3 Versuchen verfügbar