2013-05-25 95 views
29
ID  parent_id name 
--------------------- 
1  2   first 
2  4   second 
3  3   third 
4  5   fourth 
5  -   fifth 

祖先first名單應該是(2, 4, 5)SQL遞歸查詢得到一個項目的所有祖先

+1

到目前爲止,您能否展示您的努力?從你的數據我看不出「第一」有2,4和5的關聯父代 – georgealton

+0

你不能只是做一個連接? – bestprogrammerintheworld

+0

在sql server中,你可以用CTE做到這一點,請參閱http://stackoverflow.com/questions/3916597/sql-server-recursive-query基本算法 –

回答

63
with name_tree as (
    select id, parent_id, name 
    from the_unknown_table 
    where id = 1 -- this is the starting point you want in your recursion 
    union all 
    select c.id, c.parent_id, c.name 
    from the_unknown_table c 
    join name_tree p on p.parent_id = c.id -- this is the recursion 
) 
select * 
from name_tree 
where id <> 1; -- exclude the starting point from the overall result 

SQLFiddle:http://sqlfiddle.com/#!3/87d0c/1

+0

非常漂亮。我實際上是在尋找一個遞歸函數來存儲過程來做這件事情。 –

+0

@a_horse_with_no_name - 先生,先生。 – Buggieboy

+1

這似乎並不奏效 - 只返回第一行。我錯過了什麼? – Andrey

11

您可以使用這樣的事情:

with parents as 
(
    select ID, parent_ID 
    from t 
    where parent_ID is not null 
    union all 
    select p.ID, t.parent_ID 
    from parents p 
    inner join t on p.parent_ID = t.ID 
     and t.parent_ID is not null 
     and t.ID <> t.parent_ID 
) 
select * 
    , parents = '(' + stuff 
    (
     (
     select ', ' + cast(p.parent_ID as varchar(100)) 
     from parents p 
     where t.ID = p.ID 
     for xml path('') 
    ), 1, 2, '' 
    ) + ')' 
from t 
order by ID 

SQL Fiddle with demo

這結合了兩種非常常見的T-SQL技術 - 使用CTE來獲取層次結構並使用FOR XML PATH獲取CSV列表。

+0

這效果很好 – Andrey

+0

好答案+解釋,很好! –