我发现的所有递归CTE示例都使用了基本相同的场景。它们都在组织结构图中向上或向下移动。我的CTE非常适合一对一的父母/子女关系,比如一个员工有一个经理,但我有一张桌子,孩子可以有多个父母。我想要的是一个来自一个孩子的父母身份证明的清单。
如果您对细节感兴趣,我将通过MS Project文件中特定任务的前身进行递归。我想从一个特定的里程碑开始,一直追溯到文件的顶部,以便找到可能影响里程碑的任何前辈。您可能知道,任务可以有多个前任。
我的关系看起来像这样:
tblTasks
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,它会返回数百万条记录。
我可能做错了什么?
答案 0 :(得分: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
不知道它是否会更快,请自行检查。
答案 1 :(得分:0)
我认为没有比DISTINCT
更好的表现选项。
您不能使用LEFT JOIN
来限制trace.Task IS NULL
的位置,您不能GROUP BY
。我认为DISTINCT
是要走的路。