2012-03-13 49 views
1

假設這臺SQL父子樹排序順序

ParentId ChildId SortOrder 
--------------------------------- 
0   1   0 
1   2   1 
2   3   1 
2   4   2 
2   6   3 
1   7   2 
1   9   3 
9   10   1 
9   12   2 

如何將我寫一個簡單的CTE(或其他類型的查詢),將返回他們的父/子關係,在任何級別,但保持排序 - 爲父母下方的所有子項目訂購。

基本上,這將是一個簡單的樹視圖,其中子項按特定的排序順序排列。

的SQL Server 2008是DB

更新: 可以有無限的父/子級別 - 我嘗試從其它棧的問題/回答一些例子,但沒有包括在子級別排序順序。

一個例子的結果應該是:

parent (sort 0) 
    child (sort 1) 
    child (sort 2) 
    child (sort 3) 
     child-child (sort 1) 
    child (sort 4) 
     child-child (sort 1) 
     child-child (sort 2) 

希望這是有道理的 - 也許我是看着這個錯誤,這種結果是更好地進行中期內構建梯隊?

反正,任何反饋非常讚賞

+1

你能給什麼樣的結果,是爲了看起來像一個例子? – hofnarwillie 2012-03-13 00:21:24

回答

7

具有特殊排序覆蓋的遞歸CTE。注意在2孩子的那種倍率(我修改源表略有測試這種能力)

declare @relations table(ParentID int, ChildID int, SortOrder int, treeID int); 

insert into @relations values 
(0,1,0,0), (1,2,1,0), (2,3,2,0), (2,4,1,0), (2,6,3,0), (1,7,2,0), (1,9,3,0), (9,10,1,0), (9,12,2,0) --tree 0 
, (0,1,0,1), (1,2,1,1), (2,3,2,1), (2,4,1,1), (2,6,3,1), (1,7,2,1), (1,9,3,1), (9,10,1,1), (9,12,2,1) --tree 1 

; with cte(ParentId,ChildId,SortOrder,depth,agg,treeID) as (
    select null,ParentId,SortOrder,0 
    , right('0000000'+CAST(treeID as varchar(max)),7) 
     +right('0000000'+CAST(SortOrder as varchar(max)),7) 
    , treeID 
    from @relations where ParentId=0 
    union all 
    select cte.ChildId,r.ChildId,r.SortOrder,cte.depth+1 
    , cte.agg 
     +right('0000000'+CAST(r.treeID as varchar(max)),7) 
     +right('0000000'+CAST(r.SortOrder as varchar(max)),7) 
     +right('0000000'+CAST(r.ChildId as varchar(max)),7) 
    , r.treeID 
    from cte 
    inner join @relations r on r.ParentID=cte.ChildId 
    where cte.depth<32767 
    and r.treeID=cte.treeID 
) 
select 
tree=case depth when 1 then cast(ParentID as varchar(30))+' (sort '+cast(SortOrder as varchar(30))+')' 
    else REPLICATE(CHAR(9),depth-1) 
     + cast(ChildId as varchar(30))+' (sort '+cast(SortOrder as varchar(30))+')' 
    end 
from cte 
where depth>0 
order by agg 
option (maxrecursion 32767); 

結果:

tree 
-------------------------------------------------- 
0 (sort 0) 
    2 (sort 1) 
     4 (sort 1) 
     3 (sort 2) 
     6 (sort 3) 
    7 (sort 2) 
    9 (sort 3) 
     10 (sort 1) 
     12 (sort 2) 
0 (sort 0) 
    2 (sort 1) 
     4 (sort 1) 
     3 (sort 2) 
     6 (sort 3) 
    7 (sort 2) 
    9 (sort 3) 
     10 (sort 1) 
     12 (sort 2) 
+0

哇 - 這將需要一些時間來研究:)感謝您的偉大答案 – Andre 2012-03-13 03:36:52

+0

嘿約翰 - 在這裏使用你的例子,並與一些事情(可能微不足道)掙扎。我如何修改這條語句,以便我可以在表格中存儲多棵樹?意思是,如果我只有一個主根(其中parentid = 0),如果我想存儲一個單獨的樹(parentid = 0),並使用「from @relations where ParentId = 0和childid = 45) - 目前這似乎不符合這個聲明?希望這是有道理的 – Andre 2012-03-30 21:53:37

+1

嗨安德烈。看起來像你喜歡具有挑戰性的問題:) 這可能有點設計,但我添加了一個基於0我修改了上面的解決方案,以顯示兩棵外表相同的樹,它們只通過它們的treeID區分開來。 – 2012-04-02 03:56:51

0

聲音幾乎相同的另一個我回答here你必須改變由一個小的順序。