Chuyển đến nội dung chính
Mô-đun 7 · Bài học 4 trong tổng số 428/57 trong khóa học~14 min
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

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;

Nó hoạt động như thế nào trong thực tế:

  1. PostgreSQL thực thi thuật ngữ cơ sở một lần.
  2. 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).
  3. Lặp lại bước 2 cho đến khi thuật ngữ đệ quy tạo ra 0 hàng mới.
  4. Kết quả cuối cùng là UNION ALL của tất cả các bước.

Ví dụ 1: cây có chiều sâu và đường đi

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;

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.

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;

Hãy thử nó

tập thể dục#sql.m7.l4.e1
Nỗ lực: 0Đang tải…

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.

Đang tải trình chỉnh sửa…
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

tập thể dục#sql.m7.l4.e2
Nỗ lực: 0Đang tải…

Đố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.

Đang tải trình chỉnh sửa…
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ử