2011-04-19 52 views
3

this answer我問如何獲得所有的子節點,並且還有一個對根節點的引用。現在我意識到,我也需要相反的:sql server如何檢索從樹中的任何孩子到祖先的所有節點?

我想擁有所有的節點和所有的父母。

所以在這個簡單的樹:

1 - 2 - 3 

    L - 4 - 5 

     L - 6 

7 - 8 

我想有

1 1; 
2 2; 
2 1; 
3 3; 
3 2; 
3 1; 
4 4; 
4 2; 
4 1; 
5 5; 
5 4; 
5 2; 
5 1; 
6 6; 
6 4; 
6 2; 
6 1; 
7 7; 
8 8; 
8 7; 

(順序並不重要)

這是查詢,以獲取相反(從父母獲得所有孩子)。我試圖用它玩,但找不到解決方案。你能建議嗎?

-- get all childs of all parents 
WITH q AS 
     (
     SELECT ID_CUSTOMER, ID_CUSTOMER AS root_customer 
     FROM CUSTOMERS c 
     UNION ALL 
     SELECT c.ID_CUSTOMER, q.root_customer 
     FROM q 
     JOIN CUSTOMERS c 
     ON  c.ID_PARENT_CUSTOMER = q.ID_CUSTOMER 
     ) 
SELECT * 
FROM q 

回答

3

該查詢建立鄰接表的transitive closure:所有祖先子孫對的列表。

因爲它會爲每個祖先返回所有的後代,相反的情況也是如此:對於每個後代它將返回所有的祖先。

所以這個查詢確實會返回所有可能的組合,不管遍歷順序如何:無論您是父母連接到孩子還是其他方式都無關緊要。

測試一下:

WITH customers (id_customer, id_parent_customer) AS 
     (
     SELECT * 
     FROM (
       VALUES (1, NULL), 
         (2, 1), 
         (3, 2), 
         (4, 2), 
         (5, 4), 
         (6, 4), 
         (7, NULL), 
         (8, 7) 
       ) t (a, b) 
     ), 
     q AS 
     (
     SELECT ID_CUSTOMER, ID_CUSTOMER AS root_customer 
     FROM CUSTOMERS c 
     UNION ALL 
     SELECT c.ID_CUSTOMER, q.root_customer 
     FROM q 
     JOIN CUSTOMERS c 
     ON  c.ID_PARENT_CUSTOMER = q.ID_CUSTOMER 
     ) 
SELECT * 
FROM q 
ORDER BY 
     id_customer, root_customer DESC 
+0

是的,這是偉大的。感謝您的解釋,這正是我所要求的。 – LaBracca 2011-04-19 14:22:27

+0

這也返回1,1 ... 2,2。如果我想排除這些,我會怎麼做? – 2017-09-21 20:54:15

0
with q (
select id_customer, id_parent_customer from customers 
union all 
select id_customer, id_parent_customer from customers 
join q on customers.id_parent_customer = q.id_customer 
) select * from q 
相關問題