שיעורי מודול (4/4)
CTEs רקורסיביים: היררכיות עומק שרירותיות
חיבור עצמי (מודול 5) מוצא רק רמה אחת של היררכיה: ילד → הורה. אבל מה קורה אם ההיררכיה היא בעומק של 3, 5 או n רמות, ואתה לא יודע מראש כמה? אתה צריך CTEs רקורסיבי: א CTE שמתייחסת לעצמה כדי "להרחיב" את התוצאות באופן איטרטיבי.
במערך הנתונים ecommerce, לטבלה categories יש 3 שורשים
(Elettronica, Libri, Casa) ו-2 ילדים כל אחד - עץ בן 2 מפלסים. זה א
מקרה פשוט אבל מספיק כדי ללמוד את הדפוס.
התחביר
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;איך זה עובד בפועל:
- PostgreSQL מבצע את מונח הבסיס פעם אחת.
- הוא מבצע את המונח הרקורסי באמצעות השורות שהופקו זה עתה "קלט" (לא כל ה-CTE: רק התוספת).
- הוא חוזר על שלב 2 עד שהמונח הרקורסי מייצר 0 שורות חדשות.
- התוצאה הסופית היא
UNION ALLשל כל השלבים.
דוגמה 1: עץ עם עומק ושביל
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). השני איטרציה מוצאת את 6 הילדים (רמה 2). האיטרציה השלישית מוצאת שום דבר → נעשה.
דוגמה 2: בהינתן צומת, מצא את השורש שלו
גרסה של "מלמעלה למטה → מלמטה למעלה": אנו מפיצים את המזהה של השורש למטה העץ.
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;נסה את זה
השתמש ב-CTE רקורסיבי בשם 'עץ' כדי לשטח את היררכיית הקטגוריות. הצג מזהה, שם, עומק (1 לשורשים, 2 לילדים וכו') ונתיב (למשל 'Elettronica > Audio'). סדר לפי נתיב.
הצג רמז
ה-JOIN במונח הרקורסי מקשר את c.parent_id לשורה שכבר קיימת בעץ (t.id).
הפתרון זמין לאחר 3 ניסיונות
סקירת התרגיל
עבור כל קטגוריה, הצג id, name ו-root_name (שם קטגוריית השורש בראש העץ שאליו היא שייכת). לשורשים יש root_name = שם. הזמנה לפי תעודת זהות.
הצג רמז
הפיצו root_name מהאב (t.root_name) לילד (c).
הפתרון זמין לאחר 3 ניסיונות