Câu hỏi được đặt ra
Bạn không thể tham chiếu một bí danh bảng từ một truy vấn con trong một truy vấn khác ở cùng cấp độ (hoặc trong một phần khác của UNION
truy vấn). Bí danh bảng chỉ hiển thị trong chính truy vấn và các truy vấn phụ của nó.
Bạn có thể tham chiếu các cột đầu ra của truy vấn con ở cùng cấp truy vấn với LATERAL JOIN
. Ví dụ:
Tìm các phần tử phổ biến nhất trong mảng với một nhóm theo
Giải pháp cho số cấp tối đa nhỏ
Chỉ dành cho một số cấp độ (nếu bạn biết tối đa), bạn có thể sử dụng một truy vấn đơn giản:
-
LEFT JOIN
đến n-1 phiên bản của chính bảng - Sử dụng
COALESCE
vàCASE
câu lệnh ghim root và hight,
SELECT p1.c AS child, COALESCE(p3.p, p2.p, p1.p) AS parent
,CASE
WHEN p3.p IS NOT NULL THEN 3
WHEN p2.p IS NOT NULL THEN 2
ELSE 1
END AS height
FROM parent p1
LEFT JOIN parent p2 ON p2.c = p1.p
LEFT JOIN parent p3 ON p3.c = p2.p
WHERE p1.c IN (3, 8)
ORDER BY p1.c;
Đây là SQL tiêu chuẩn và sẽ hoạt động trong cả 4 RDBMS bạn đã gắn thẻ.
Giải pháp chung cho số cấp tùy ý
Sử dụng CTE đệ quy như @Ken đã tư vấn.
- Trong chân đệ quy, giữ con đối với mỗi hàng, chỉ nâng cấp hàng chính.
- Trong
SELECT
bên ngoài , chỉ giữ một hàng cóheight
lớn nhất mỗi đứa trẻ.
WITH RECURSIVE cte AS (
SELECT c AS child, p AS parent, 1 AS height
FROM parent
WHERE c IN (3, 8)
UNION ALL
SELECT c.child, p.p AS parent, c.height + 1
FROM cte c
JOIN parent p ON p.c = c.parent
-- WHERE c.height < 10 -- to safeguard against endless loops if necessary
)
SELECT DISTINCT ON (child) *
FROM cte
ORDER BY child, height DESC;
DISTINCT ON
dành riêng cho Postgres . Giải thích:
Chọn hàng đầu tiên trong mỗi GROUP BY nhóm?
Phần còn lại sẽ hoạt động theo cách tương tự trong Oracle và thậm chí cả SQLite , nhưng không phải trong MySQL không hỗ trợ CTE.
SQL Fiddle thể hiện cả hai.