我有两个包含这样数据的表(要创建的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
答案 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