الانتقال إلى المحتوى الرئيسي
الوحدة 7 · الدرس 4 من 428/57 في الدورة~14 min
دروس الوحدة (4/4)

CTEs العودية: التسلسلات الهرمية التعسفية

تعثر عملية الانضمام الذاتي (الوحدة 5) على ** مستوى واحد فقط ** من التسلسل الهرمي: الطفل → الوالدين. ولكن ماذا يحدث إذا كان التسلسل الهرمي بعمق 3 أو 5 أو n مستويات، وأنت لا تعرف مقدما كم؟ أنت بحاجة إلى CTEs العودية: أ CTE الذي يشير إلى نفسه "لتوسيع" النتائج بشكل متكرر.

في مجموعة البيانات ecommerce، يحتوي الجدول categories على 3 جذور (Elettronica، Libri، Casa) وطفلين لكل منهما - شجرة ذات مستويين. انها أ حالة بسيطة ولكنها كافية لتعلم النمط.

بناء الجملة

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;

كيفية العمل على أرض الواقع:

  1. ينفذ PostgreSQL المصطلح الأساسي مرة واحدة.
  2. يقوم بتنفيذ المصطلح العودي باستخدام الصفوف التي تم إنتاجها للتو "الإدخال" (وليس CTE بالكامل: الزيادة فقط).
  3. يكرر الخطوة 2 حتى ينتج المصطلح العودي 0 صفوف جديدة.
  4. النتيجة النهائية هي UNION ALL لجميع الخطوات.

مثال 1: شجرة ذات عمق ومسار

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;

ينتج عن التكرار الأول 3 صفوف (الجذور عند المستوى 1). الثاني يجد التكرار الأطفال الستة (المستوى 2). يجد التكرار الثالث لا شيء → تم.

مثال 2: في حالة وجود عقدة، ابحث عن جذرها

متغير "من أعلى إلى أسفل → من أسفل إلى أعلى": نقوم بنشر معرف الجذر للأسفل الشجرة.

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;

جربه

تمرين#sql.m7.l4.e1
المحاولات: 0جارٍ التحميل…

استخدم CTE العودي المسمى "شجرة" لتسوية التسلسل الهرمي للفئة. إظهار المعرف والاسم والعمق (1 للجذور، 2 للأطفال، وما إلى ذلك) والمسار (على سبيل المثال، "Elettronica > Audio"). الترتيب حسب المسار.

جارٍ تحميل المحرر…
إظهار التلميح

تربط JOIN في المصطلح العودي c.parent_id بالصف الموجود بالفعل في الشجرة (t.id).

الحل متاح بعد 3 من المحاولات

تمرين المراجعة

تمرين#sql.m7.l4.e2
المحاولات: 0جارٍ التحميل…

لكل فئة، قم بإظهار المعرف والاسم واسم الجذر (اسم فئة الجذر في أعلى الشجرة التي تنتمي إليها). الجذور لها root_name = name. الطلب حسب المعرف.

جارٍ تحميل المحرر…
إظهار التلميح

نشر root_name من الأصل (t.root_name) إلى الطفل (c).

الحل متاح بعد 3 من المحاولات