2013-10-24 85 views
1

我發現的所有遞歸CTE示例都使用基本相同的場景。他們都在一個組織結構圖上往下走。我的CTE非常適合一對一的父母/子女關係,比如一個員工有一個經理,但是我有一張表,孩子可以有多個父母。我想要的是一個源自一個孩子的母親身份證明表。具有多個父項的T-SQL遞歸CTE

如果你對細節感興趣,我將通過MS Project文件中特定任務的前輩進行遞歸。我想從一個特定的里程碑開始,一直追溯到文件的頂部,以便找到可能影響里程碑的任何前任。如您所知,任務可以有多個前任。

我的關係是這樣的:

tblTask​​s

child parent 
3  1 
16  1 
25  1 
25  3 
25  16 
26  1 
26  3 
27  25 
27  26 

這裏是我的CTE:

;WITH ProjectTrace(Task) 
AS 
(
    -- Anchor member definition (This is task 27) 
    SELECT t.parent AS Task 
    FROM #tblTasks t 
    WHERE t.child = 27 

    UNION ALL 

    -- Recursive member definition (This is everything that hooks into 27 via predecessors) 
    SELECT t.parent AS Task 
    FROM #tblTasks t 
    INNER JOIN ProjectTrace trace 
     ON t.child = trace.Task 
) 
SELECT * FROM ProjectTrace ORDER BY Task 

我想供應任務#27到查詢,並且僅獲得1,3,16,25,26在我的結果集。但是,由於方式的遞歸工作,我的結果集是這樣的:

Task 
1 
1 
1 
1 
1 
3 
3 
16 
25 
26 

如果你看的關係,我想這是有道理的。我總是可以將選擇結果更改爲不同的選擇,但是當我深入瞭解項目時,請說任務編號500,它會返回數百萬條記錄。

我會做什麼錯?

+1

上次選擇時丟失了「DISTINCT」? – Dan

+0

這個問題沒有錯......問題是什麼?添加獨特的,你是gtg – Hogan

+0

正如我在我的原始文章中所說: 「我總是可以改變選擇一個結束選擇不同,但是當我深入到項目中,說任務號碼500,它返回數百萬條記錄「。 –

回答

0

我認爲distinct是做這件事的好方法。您也可以檢查迭代插入解決方案:

declare @Temp table(Task int primary key) 

insert into @Temp 
select distinct parent from Table1 where child = 27 

while 1 = 1 
begin 
    insert into @Temp 
    select distinct T.parent 
    from Table1 as T 
    where 
     exists (select * from @Temp as TT where TT.Task = T.child) and 
     not exists (select * from @Temp as TT where TT.Task = T.parent) 

    if @@rowcount = 0 break 
end 

select * from @Temp 

不知道是否會更快,請自行檢查。

+0

謝謝羅馬!這是完美的,它的運行速度比CTE快。如果你能解釋它在做什麼,會喜歡它。 –

+0

@KevinSlane基本上不會插入給定子的結果集父項,然後運行無限循環,檢查是否有任何記錄中的@ Temp'id和父項不是子項,然後插入,如果有這樣的項記錄。 –

+0

謝謝!它確實讓我知道了這個諺語。非常適合我們! –

0

我不認爲有比DISTINCT更好的表演選項。

您不能使用LEFT JOIN來限制trace.Task IS NULL,您不能GROUP BY。我認爲DISTINCT是要走的路。

+0

這很不幸。如果是這樣,恐怕CTE解決方案不適合我。我不確定是否有更好的報告,但我無法發佈需要幾分鐘才能運行的報告。那麼,我**可以**,但我不會那樣結交很多朋友。 :) –