2012-10-31 41 views
3

我有一個所謂的項目表,包含這些列的數據庫:在自引用表編寫一個遞歸SQL查詢

  • ID - 主鍵,唯一標識符
  • 名稱 - 爲nvarchar(256)
  • PARENTID - 唯一標識符

名稱字段可以被用來構建出到項的路徑,通過各自的ParentId迭代,直到它等於「11111111-1111-1111-1111-111111111111」,這是一個根項目。

所以,如果你有一個表,有一個像

ID         Name  ParentID 
------------------------------------------------------------------------------------- 
11111111-1111-1111-1111-111111111112 grandparent 11111111-1111-1111-1111-111111111111 
22222222-2222-2222-2222-222222222222 parent  11111111-1111-1111-1111-111111111112 
33333333-3333-3333-3333-333333333333 widget  22222222-2222-2222-2222-222222222222 

所以,如果我擡起頭來,在上面的例子ID「33333333-3333-3333-3333-333333333333」的項目行,我會想路徑

/grandparent/parent/widget 

返回。我試圖編寫一個CTE,因爲看起來像你通常會這樣做 - 但是因爲我沒有做太多的SQL,所以我無法弄清楚我哪裏出錯了。我已經看過一些例子,這和我似乎能夠得到的一樣接近 - 它只返回子行。

declare @id uniqueidentifier 
set @id = '10071886-A354-4BE6-B55C-E5DBCF633FE6' 
;with ItemPath as (
    select a.[Id], a.[Name], a.ParentID 
     from Items a 
      where Id = @id 

    union all 

    select parent.[Id], parent.[Name], parent.ParentID 
     from Items parent 
      inner join ItemPath as a 
       on a.Id = parent.id 
        where parent.ParentId = a.[Id] 
) 
select * from ItemPath 

我不知道如何我會申報路徑的局部變量,並保留追加到它的遞歸查詢。在去之前,我會試着至少把所有的行都交給父母。如果任何人都可以提供幫助 - 我會很感激。

回答

11

那麼這裏的工作液

SQL FIDDLE EXAMPLE

declare @id uniqueidentifier 
set @id = '33333333-3333-3333-3333-333333333333' 

;with ItemPath as 
(
    select a.[Id], a.[Name], a.ParentID 
    from Items a 
    where Id = @id 

    union all 

    select parent.[Id], parent.[Name] + '/' + a.[Name], parent.ParentID 
    from ItemPath as a 
     inner join Items as parent on parent.id = a.parentID 
) 
select * 
from ItemPath 
where ID = '11111111-1111-1111-1111-111111111112' 

我不喜歡它了,我認爲更好的解決方案將是左右做其他的方式。等一下,我嘗試寫另一個查詢:)

UPDATE這裏是

SQL FIDDLE EXAMPLE

create view vw_Names 
as 
    with ItemPath as 
    (
     select a.[Id], cast(a.[Name] as nvarchar(max)) as Name, a.ParentID 
     from Items a 
     where Id = '11111111-1111-1111-1111-111111111112' 

     union all 

     select a.[Id], parent.[Name] + '/' + a.[Name], a.ParentID 
     from Items as a 
      inner join ItemPath as parent on parent.id = a.parentID 
    ) 
select * 
from ItemPath 

,現在你可以使用這個觀點

declare @id uniqueidentifier 
set @id = '33333333-3333-3333-3333-333333333333' 

select * 
from vw_Names where Id = @id 
+0

當我嘗試運行這些,我得到這個錯誤:'類型不錨和遞歸查詢的列「姓名」,「ItemPath」 .' 任何想法遞歸部分之間的匹配爲什麼? –

+0

我能夠通過將兩個名稱字段都轉換爲nvarchar(255),thx來解決這個問題。 –

+0

是的,我認爲在CTE視圖的第一部分中使用nvarchar(max)會更好,我已經更改了答案 –

1

我需要這個答案略有不同,因爲我想生成樹中所有譜系的列表。我也想知道每個節點的深度。我添加了一個頂級父母的臨時表,我可以通過這個表和一個臨時表來構建結果集。

use Items 

    Select * 
    Into #Temp 
    From Items 
    where ParentID=0 

    Declare @Id int 

    create table #Results 
    (
     Id int, 
     Name nvarchar(max), 
     ParentId int, 
     Depth int 
    ) 
    While (Select Count(*) From #Temp) > 0 
    Begin 
     Select Top 1 @Id = Id From #Temp 
     begin 
      with ItemPath as 
      (
       select a.[Id], cast(a.[Name] as nvarchar(max))as Name, a.ParentID ,1 as 
Depth 
       from Items a 
       where a.ID = @id 

       union all 

       select a.[Id], parent.[Name] + '/' + a.[Name], a.ParentID, 1 + Depth 
       from Items as a 
        inner join ItemPath as parent on parent.id = a.parentID 
      ) 
      insert into #Results 
      select * 
      from ItemPath 
     end   
     Delete #Temp Where Id = @Id    
    End 
    drop table #Temp   
    select * from #Results 
    drop table #Results 

如果我們從下表中開始......

Id Name ParentID 
1 Fred 0 
2 Mary 0 
3 Baker 1 
4 Candle 2 
5 Stick 4 
6 Maker 5 

我們會得到這樣的結果表。

Id Name     ParentID Depth 
1 Fred     0  1 
2 Mary     0  1 
3 Fred/Baker    1  2 
4 Mary/Candle    2  2 
5 Mary/Candle/Stick  4  3 
6 Mary/Candle/Stick/Maker 5  4