自引用表上的递归查询(不是分层的)

时间:2011-01-07 10:55:04

标签: sql tsql

我正在创建一个状态图表,数据存储在一个简单的自引用表(JobPath)中

JobId - ParentJobId

我使用标准的SQL CTE来获取数据,这些数据一直运行良好,直到我得到以下数据

JobId - ParentId
  1        2
  2        3
  3        4
  4        2

现在您可以看到作业2的作业4链接到作业3,然后转到作业4,依此类推。

有什么方法可以告诉我的查询不要提取它已有的数据吗?


这是我当前的查询

WITH JobPathTemp (JobId, ParentId, Level)
AS
(
-- Anchor member definition
    SELECT j.JobId, jp.ParentJobId, 1 AS Level
    FROM Job AS j
    LEFT OUTER JOIN dbo.JobPath AS jp
        ON j.JobId = jp.JobId
    where j.JobId=1516
    UNION ALL
-- Recursive member definition
    SELECT  j.JobId, jp.ParentJobId, Level + 1
    FROM dbo.Job as j
    INNER JOIN dbo.JobPath AS jp
        ON j.JobId = jp.JobId
    INNER JOIN JobPathTemp AS jpt
        ON jpt.ParentId = jp.JobId
      WHERE jp.ParentJobId <> jpt.JobId 
)

- 执行CTE的声明

SELECT * FROM JobPathTemp

2 个答案:

答案 0 :(得分:3)

如果您没有处理大量条目,则以下解决方案可能适用。我们的想法是为每一行构建完整的“id路径”,并确保“当前id”(在递归部分中)尚未处于正在处理的路径中:

(为了测试目的,我删除了连接到jobpath,但基本模式应该相同)

WITH JobPathTemp (JobId, ParentId, Level, id_path)
AS
(
  SELECT jobid, 
         parentid, 
         1 as level, 
         '|' + cast(jobid as varchar(max)) as id_path
  FROM job
  WHERE jobid = 1

  UNION ALL

  SELECT  j.JobId, 
          j.parentid, 
          Level + 1, 
          jpt.id_path + '|' + cast(j.jobid as varchar(max))
  FROM Job as j
    INNER JOIN JobPathTemp AS jpt ON j.jobid = jpt.parentid 
                                     AND charindex('|' + cast(j.jobid as varchar), jpt.id_path) = 0
)
SELECT *
FROM JobPathTemp
;

答案 1 :(得分:0)

此解决方案不起作用,SQL Server不支持使用UNION将递归术语连接在一起。既然你不能引用递归,除了作为连接,tbh我没有看到使用存储函数的任何替代...


您没有发布您的查询...但我尝试过(在postgres中,它以相同的方式工作)如果您在递归术语中使用“UNION”(而不是“UNION ALL”),那么它应该自动删除重复的行:

with /*recursive*/ jobs as
 (select jobpath.jobid, jobpath.parentjobid from jobpath where jobid = 1
  union
  select jobpath.jobid, jobpath.parentjobid
  from jobpath
       join jobs on jobs.parentjobid = jobpath.jobid
 )
select jobpath.* from jobpath join jobs on jobpath.jobid = jobs.jobid;