CTE рекурсивно обновляет значения полей, пока не останется никакого значения по умолчанию - PullRequest
0 голосов
/ 03 июля 2018

Я пытаюсь написать рекурсию, которая обновляет значения поля, пока не останется значение по умолчанию '0'.

Отправной точкой является эта таблица:

    USE [Test]

    DROP TABLE IF EXISTS [Test].[dbo].[T0]

    CREATE TABLE [Test].[dbo].[T0] (
    ID1 nvarchar(50),
    ID2 nvarchar(50),
    Score decimal(18,0),
    tag int
    );

    INSERT INTO [Test].[dbo].[T0] (ID1, ID2, Score, tag)
    VALUES ('A1', 'B1', 100.0, 0),
    ('A1', 'B2', 90, 0),
    ('A2', 'B1', 80, 0),
    ('A2', 'B3', 70, 0),
    ('A3', 'B4', 85, 0),
    ('A4', 'B4', 75, 0),
    ('A5', 'B5', 85, 0),
    ('A5', 'B6', 75, 0);

Задача для всех строк с [tag] = 0:

  1. обновить значение поля [tag] до '1' до строки с наивысшей оценкой,

  2. обновить значение поля [tag] до '2', чтобы строки имели тот же [ID1] или [ID2], что и строка с наибольшим счетом.

Рекурсия должна продолжаться до тех пор, пока не останется больше строк со значением '0'.

Желаемый вывод выглядит так:

ID1 ID2 Score   tag
A1  B1  100 1
A1  B2  90  2
A2  B1  80  2
A2  B3  70  1
A3  B4  85  1
A4  B4  75  2
A5  B5  85  1
A5  B6  75  2

Я написал следующий CTE, который не зацикливается. Мне нужно запустить его четыре раза, чтобы получить правильный вывод.

WITH T1 AS
(
    Select distinct [ID1], [ID2], [Score], [tag]
    ,Rank() over (order by [Score] desc, [ID1] desc, [ID2] desc) as [rk]
    from [Test].[dbo].[T0] 
    where [tag] = 0
    group by [ID1], [ID2], [Score], [tag]

)
,T2 AS
(
    Select distinct [ID1], [ID2]
    ,[Score]
    ,[rk]
    ,case when rk = 1 then 1 else [tag] end as [tag]
    from [T1]
)

,T3 AS
(
    Select [ID1], [ID2], [Score], 0 as rk, case when rk <> 1 and ([Top_ID1] is not null or [Top_ID2] is not null) then 2 else [tag] end as [tag]
    from 

        (Select [ID1], [ID2], [Score], rk, tag from [T2]) T3_1
        left outer join
        (Select  [ID1] as [Top_ID1], [ID2] as [Top_ID2] from [T2] where  rk = 1) T3_2
        on T3_1.[ID1] = T3_2.[Top_ID1] or T3_1.[ID2] = T3_2.[Top_ID2]
)
,T4 AS
(
    Select distinct [ID1], [ID2], [Score], [rk], [tag] 
    from [T3]
    where [tag] = 0 

    union all

    Select [ID1], [ID2], [Score], [rk], [tag] 
    from [T4]
    where [tag] = 0 
)
Update [Test].[dbo].[T0]
Set [tag] = [T4].[tag]
from [T4]
join [Test].[dbo].[T0] D on D.[ID1] = [T4].[ID1] and D.[ID2] = [T4].[ID2]
option ( MaxRecursion 0 );

Кто-нибудь знает, как изменить код для работы рекурсии?

Спасибо за вашу помощь!

...