如何用CTE解决这个问题?

时间:2013-09-13 15:02:44

标签: sql sql-server tsql recursion common-table-expression

我有一张将工作链接在一起的表格:

JobToJob
(
   JobToJobId int 
   SourceJobId int
   DestinationJobId int 
)

作业可以有多个目标作业(即多于1个JobToJob记录),但只有1个源作业。所以这会创建一个树结构。根记录定义为在任何其他记录上没有DestinationJobId条目的根记录。

我的要求是检索提供的作业ID的整个树。我将其分为两部分:

  1. 找到给定作业ID的根作业
  2. 检索根作业ID的所有叶子。
  3. 我已经尝试过使用递归CTE,但我没有得到任何结果。我知道我可以通过使用存储过程来做到这一点,但是我试图避免这样做,因为它们往往会减慢速度。

    有没有比我具有更多递归CTE经验的人有任何关于最佳方法的建议?

    干杯,

    罗布

2 个答案:

答案 0 :(得分:0)

您使用术语“叶子”,这意味着没有目的地的作业(而不是树中的中间节点)。

这是一种方法。从所有树叶开始,然后爬上树,连接它们所在的所有节点。然后选择属于您感兴趣的工作的那些:

with cte as (
      select DestinationJobId as JobId, DestinationJobId as parent, 1 as level
      from jobs2jobs jj
      where DestinationJobId not in (select SourceJobId from jobs2jobs)
      union all
      select cte.JobId, jj.SourceJobId, level + 1
      from cte
           jobs2jobs jj
           on cte.Parent = jj.DestinationJobId
    )
select *
from cte
where parent = @YourJobId;

答案 1 :(得分:0)

希望你有一张乔布斯表。

declare @JobId int
;with getAscendants( job, parent, inverseDepth)
as
(
  select jj.DestinationJobId, jj.SourceJobId, 1
  from JobToJob jj 
  where jj.DestinationJobId = @JobId

  union all

  select jj.DestinationJobId, jj.SourceJobId, inverseDepth + 1
  from getAscendants
  join JobToJob jj on jj.DestinationJobId = getAscendants.parent
)
,rootFinder( job)
as
(
  select j.JobId
  from Jobs j
  where j.JobId = coalesce
  (
    (
      select top 1 parent from getAscendants order by inverseDepth desc
    )
    , @JobId
  )
)
,getDescendants( job, parent)
as
(
  select j.JobId, null
  from Jobs j
  cross apply rootFinder 
  where j.JobId = rootFinder.job

  union all

  select jj.DestinationJobId, jj.SourceJobId 
  from getDescendants
  join JobToJob jj on jj.SourceJobId = getDescendants.job
) 
select * from getDescendants