Tsql递归查询 - 最后一个活动的Id

时间:2018-05-22 10:54:32

标签: tsql recursive-query

我有两个包含这样数据的表(要创建的T-sql代码):

CREATE TABLE [dbo].[IdChanges](
    [ReplacedId] [int] NOT NULL,
    [OverrideId] [int] NOT NULL 
);
INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(17,18);
INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(18,19);
INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(19,20);
INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(12,13);
INSERT INTO dbo.IdChanges(ReplacedId,OverrideId)VALUES(13,14);

CREATE TABLE [dbo].[IdActivity](
    [Id] [int] NOT NULL,
    [IsActive] [bit] NOT NULL   
);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(14,1);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(20,1);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(17,0);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(18,0);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(19,0);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(12,0);
INSERT INTO dbo.IdActivity(Id,IsActive)VALUES(13,0);
go

如何(通过递归cte查询或其他方式)获得更改链中的每个ReplacedId和Last Override id的结果。 我期望结果如下所示。 5行......结果可能是空的

ReplacedId   LastOverrideId
17           20
18           20
19           20
12           14
13           14

2 个答案:

答案 0 :(得分:1)

递归CTE是这里的方法。确保您的IdChanges在执行前没有循环。

;WITH RecursiveActivities AS
(
    SELECT
        OriginalActivityID = I.Id,
        OverrideActivityID = I.Id,
        Level = 0
    FROM
        [dbo].[IdActivity] AS I

    UNION ALL

    SELECT
        OriginalActivityID = R.OriginalActivityID,
        OverrideActivityID = I.OverrideId,
        Level = R.Level + 1
    FROM
        RecursiveActivities AS R
        INNER JOIN [dbo].[IdChanges] AS I ON R.OverrideActivityID = I.ReplacedId
),
MaxLevelByActivity AS
(
    SELECT
        R.OriginalActivityID,
        MaxLevel = MAX(R.Level)
    FROM
        RecursiveActivities AS R
    GROUP BY
        R.OriginalActivityID
)
SELECT
    R.OriginalActivityID,
    R.OverrideActivityID
FROM
    RecursiveActivities AS R
    INNER JOIN MaxLevelByActivity AS M ON
        R.OriginalActivityID = M.OriginalActivityID AND
        R.Level = M.MaxLevel

如果您不想看到没有变化的活动,请在最后添加WHERE R.OriginalActivityID <> R.OverrideActivityID

答案 1 :(得分:0)

我没有使用IdActivity

诀窍是使基础结束具有结尾o
然后向后走

declare @t TABLE (r int NOT NULL, o int NOT NULL, primary key(r, o));
INSERT INTO @t VALUES (17,18), (18,19), (19,20), (12,13), (13,14);

with cte as 
( select t.o as origO, r, o, 0 as lvl
  from @t t
  where not exists (select 1 from @t tt where tt.r = t.o)
  union all 
  select cte.origO, t.r, t.o, lvl+1
  from cte 
  join @t t
    on t.o = cte.r
)
select c.r, c.origO as oLast
from cte c
order by c.origO, c.r