sql - 自引用表上的递归查询(非分层)

标签 sql t-sql

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

JobId - ParentJobId

我使用标准 SQL CTE 来获取数据,该数据运行良好,直到我最终得到以下数据

JobId - ParentId
  1        2
  2        3
  3        4
  4        2

现在,您可以看到作业 4 链接到作业 2,作业 2 链接到作业 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

最佳答案

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

(出于测试目的,我删除了对作业路径的连接,但基本模式应该是相同的)

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
;

关于sql - 自引用表上的递归查询(非分层),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4624755/

相关文章:

MySQL随机排序并保存在数据库中,无需ID

mysql - 限制mysql中查询数据

sql - 如何将分钟转换为 HH :MM format

java - Oracle 中是否有函数/SQL 查询可以过滤数据(如果可以转换为日期时间)?

sql - 如何在单个 SQL 查询中获取最新日期和日期以来的所有内容

sql-server-2005 - 是否可以将表名传递到存储过程中并在没有 Exec 函数的情况下使用它?

MySQL 查询 : How to fix Error 1052 (ambiguous column)

t-sql - 我可以使用不带括号的 PIVOT 吗?

sql-server - 临时表、列名称或提供的值的数量与表定义不匹配

t-sql - Azure Synapse 无服务器 - Azure Synapse 无服务器池中的流加载 Parquet 意外结束