Tsql Рекурсивный запрос - последний активный идентификатор - PullRequest
0 голосов
/ 22 мая 2018

У меня есть две таблицы с такими данными (код 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в цепочке изменений.Я ожидаю, что результат в точности как ниже.5 строк ... Возможен ноль в результате

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

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Я не использовал 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
0 голосов
/ 22 мая 2018

Рекурсивный 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 в конце.

...