Bài học theo mô-đun (4/4)
CTE đệ quy: phân cấp độ sâu tùy ý
Tự THAM GIA (Mô-đun 5) chỉ tìm thấy chỉ một cấp của hệ thống phân cấp: con → cha mẹ. Nhưng điều gì sẽ xảy ra nếu hệ thống phân cấp sâu 3, 5 hoặc n cấp, và bạn không biết trước là bao nhiêu? Bạn cần CTE đệ quy: a CTE tham chiếu đến chính nó để "mở rộng" kết quả lặp đi lặp lại.
Trong tập dữ liệu ecommerce, bảng categories có 3 gốc
(Elettronica, Libri, Casa) và mỗi đứa 2 đứa con — một cây 2 cấp độ. Đó là một
trường hợp đơn giản nhưng đủ để tìm hiểu mẫu.
Cú pháp
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;Nó hoạt động như thế nào trong thực tế:
- PostgreSQL thực thi thuật ngữ cơ sở một lần.
- Nó thực thi thuật ngữ đệ quy bằng cách sử dụng các hàng vừa được tạo dưới dạng "đầu vào" (không phải toàn bộ CTE: chỉ phần tăng).
- Lặp lại bước 2 cho đến khi thuật ngữ đệ quy tạo ra 0 hàng mới.
- Kết quả cuối cùng là
UNION ALLcủa tất cả các bước.
Ví dụ 1: cây có chiều sâu và đường đi
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;Lần lặp đầu tiên tạo ra 3 hàng (gốc ở cấp 1). thứ hai lặp lại tìm thấy 6 con (cấp 2). Lần lặp thứ ba tìm thấy không có gì → xong.
Ví dụ 2: cho một nút, tìm gốc của nó
Một biến thể "từ trên xuống → từ dưới lên": chúng ta truyền id của gốc xuống cái cây.
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;Hãy thử nó
Sử dụng CTE đệ quy có tên là 'cây' để làm phẳng hệ thống phân cấp danh mục. Hiển thị id, tên, độ sâu (1 cho gốc, 2 cho con, v.v.) và đường dẫn (ví dụ: 'Elettronica > Audio'). Đặt hàng theo đường dẫn.
Hiển thị gợi ý
THAM GIA trong thuật ngữ đệ quy liên kết c.parent_id với hàng đã có trong cây (t.id).
Giải pháp khả dụng sau 3 lần thử
Xem lại bài tập
Đối với mỗi danh mục, hiển thị id, name và root_name (tên của danh mục gốc ở đầu cây mà nó thuộc về). Rễ có root_name = name. Đặt hàng theo id.
Hiển thị gợi ý
Truyền bá root_name từ cha mẹ (t.root_name) đến con (c).
Giải pháp khả dụng sau 3 lần thử