2013-09-28 47 views
2

我有一個表用於構建菜單項的樹結構。此表的樣本內容是以下:SQL Server - 按層次結構順序列出父記錄

Parent  Child 
------  ------ 
190   192 
192   180 
180   185 
185   184 
190   191 
191   197 
197   200 

我需要一個查詢,會給我一個逗號分隔的父記錄列表,它們出現在包括兒童ID如層次結構中的順序:

  • 考慮到孩子ID 184,它應該返回190,192,180,185,184
  • 給出的子ID 200,它應該返回190,191,197,200
+0

你試過這個嗎? http://stackoverflow.com/questions/9004543/recursive-child-parent-queries-in-t-sql – jcwrequests

+0

我不認爲這可以在單個查詢中完成,因爲您正在有效地擴展遞歸關係。我認爲可以使用存儲函數完成(我不確定SQL Server是否支持存儲函數中的遞歸)。假設它被支持,您可以輕鬆地編寫一個調用存儲函數的簡單查詢。 – Zenilogix

+0

它絕對可以在一個查詢(或兩個)中完成。如果這個問題在幾個小時內仍然開放,我會提供一個答案。 – Szymon

回答

0

爲了演示的目的,我使用了一個表變量。要使用標準表,請刪除@tempTable聲明和插入語句。然後用表名替換@tempTable引用。

declare @childId int 
set @childId = 184 

declare @tempTable table(parent int, child int) 

insert into @tempTable values(190, 192) 
insert into @tempTable values(192, 180) 
insert into @tempTable values(180, 185) 
insert into @tempTable values(185, 184) 
insert into @tempTable values(190, 191) 
insert into @tempTable values(191, 197) 
insert into @tempTable values(197, 200) 

declare @currentItem int 
set @currentItem = @childId 

declare @output varchar(max) 
set @output = cast(@currentItem as varchar) 

while (exists(select 1 from @tempTable where child = @currentItem)) 
begin 
    select 
     @currentItem = parent 
    from 
     @tempTable 
    where 
     child = @currentItem 

    set @output = cast(@currentItem as varchar) + ', ' + @output 
end 

select @output 

一些示例輸出:

爲184:190, 192, 180, 165, 184

200:190, 191, 197, 200

0

這...

Declare @data Table 
(
Parent int, 
Child int 
) 

insert into @data values 
(190, 192), 
(192, 180), 
(180, 185), 
(185, 184), 
(190, 191), 
(191, 197), 
(197, 200) 

Declare @Id as Int = 184 

/* 

    CompleteData - query produce following output 
     ID   ParentId 
     ----------- ----------- 
     180   192 
     184   185 
     185   180 
     190   NULL -- we discoverd this missing data 
     191   190 
     192   190 
     197   191 
     200   197 

    ChildHierarchyData - query produce following ouput 
     ID   ParentID Level 
     ----------- ----------- ----------- 
     184   185   0 
     185   180   1 
     180   192   2 
     192   190   3 
     190   NULL  4 

    Concatinated - query conact all ID from above result 
*/ 

;with CompleteData 
as 
(
    Select Child ID, Parent ParentId from @data 
    UNION 
    Select Child.Parent Id, Parent.Parent ParentId From @data Child 
     Left Outer Join @data Parent 
      on Child.Parent = parent.Child 
    WHERE 
     parent.Parent IS NULL 

), 
ChildHierarchyData(ID,ParentID, Level) 
as 
(
    Select ID,ParentID, 0 as Level from CompleteData Where ID = @Id 
    union all 
    Select CompleteData.ID, CompleteData.ParentID, ChildHierarchyData.Level +1 from CompleteData 
     INNER Join ChildHierarchyData 
      on ChildHierarchyData.ParentID = CompleteData.ID 
), 
Concatinated(result) 
as 
(
    Select Cast((select Cast(ID as nvarchar) + ',' [data()] from ChildHierarchyData Order By Level Desc FOR XML Path('')) as Nvarchar(max)) 
) 
select Left(result, len(result)-1) as Result from Concatinated 
0

如果您需要以逗號分隔的列表,可以很容易用遞歸CTE做:

with cte as (
    select 
     t.Parent, 1 as Level, 
     cast(t.Parent as nvarchar(max)) + ',' + cast(t.Child as nvarchar(max)) as Path 
    from Table1 as t 
    where t.Child = @Child 

    union all 

    select 
     t.Parent, Level + 1 as Level, 
     cast(t.Parent as nvarchar(max)) + ',' + c.Path as Path 
    from Table1 as t 
     inner join cte as c on c.Parent = t.Child 
) 
select top 1 Path 
from cte 
order by Level desc 

sql fiddle demo