1

我能找到的所有递归 CTE 示例都使用基本相同的场景。它们都在组织结构图上向上或向下遍历。我的 CTE 非常适用于一对一的父/子关系,例如一个员工有一个经理,但我有一张桌子,一个孩子可以有多个父母。我想要的是来自一个孩子的父母 ID 的不同列表。

如果您对细节感兴趣,我会在 MS Project 文件中递归查看特定任务的前任。我想从一个特定的里程碑开始,一直追踪到文件的顶部,以便找到可能影响里程碑的任何前辈。您可能知道,一个任务可以有多个前置任务。

我的人际关系是这样的:

任务

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

如果你看一下关系,我想这是有道理的。我总是可以将 select a end 更改为 select distinct,但是当我真正深入项目时,比如任务编号 500,它会返回数百万条记录。

我可能做错了什么?

4

2 回答 2

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

不知道会不会更快,自己查。

于 2013-10-24T19:17:35.477 回答
0

我认为没有比DISTINCT.

你不能使用 aLEFT JOIN来限制 trace.Task 的位置IS NULL,你不能GROUP BY。我认为DISTINCT是要走的路。

于 2013-10-24T19:23:46.613 回答