Рекурсивно получить последнюю запись из той же таблицы родительского потомка - PullRequest
1 голос
/ 26 марта 2019

Я хочу получить последний ссылочный идентификатор из той же таблицы. У меня есть следующая таблица.

 ID   UserId   DelegatedToUserId
 1      100       101
 2      101       102
 3      102       103
 4      103       NULL
 5      104       109

Я просто не могу разобраться. Я знаю, чего хочу, просто не могу вывести это на экран. Поэтому, когда я запрашиваю 100, запрос должен возвращать 103, когда я снова спрашиваю 101 или 102, он должен возвращать 103. Когда пользователь вводит 104, он должен возвращать 109

И когда я спрашиваю 103, он должен вернуть 103, поскольку для этого нет делегата.

это можно сделать одним SQL-запросом?

Ответы [ 2 ]

3 голосов
/ 26 марта 2019

можно ли это сделать одним SQL-запросом?

Если вы не знаете, до какого уровня может перейти иерархия, вам нужно использовать рекурсив CTE. Если это просто 1 или 2 уровень, вы можете сделать это без рекурсивного CTE в одном запросе.

Вы можете использовать рекурсив CTE, например, следующий, чтобы получить желаемый результат.

;WITH mytest 
     AS (SELECT P.userid, 
                P.delegatedtouserid, 
                1 AS LVL 
         FROM   @table P 
         WHERE  userid = 100 
         UNION ALL 
         SELECT P1.userid, 
                P1.delegatedtouserid, 
                M.lvl + 1 AS LVL 
         FROM   @table P1 
                INNER JOIN mytest M 
                        ON M.delegatedtouserid = P1.userid) 

SELECT TOP 1 WITH ties * 
FROM   mytest 
ORDER  BY Row_number() OVER (ORDER BY lvl DESC); 

Примечание : замените @table на фактическое имя таблицы.

Демонстрационная версия

1 голос
/ 26 марта 2019

Лично я бы сказал следующее:

DECLARE @UserID int = 103;

WITH VTE AS
    (SELECT *
     FROM (VALUES (1, 100, 101),
                  (2, 101, 102),
                  (3, 102, 103),
                  (4, 103, NULL),
                  (5, 104, 109)) AS V (ID, UserID, DelegatedToUserID) ),
rCTE AS
    (SELECT V.ID,
            V.UserID,
            V.DelegatedToUserID
     FROM VTE V
     WHERE UserID = @UserID
     UNION ALL
     SELECT V.ID,
            V.UserID,
            V.DelegatedToUserID
     FROM rCTE r
          JOIN VTE V ON r.DelegatedToUserID = V.UserID)
SELECT *
FROM rCTE
WHERE rCTE.DelegatedToUserID IS NULL;

Как я уже упоминал в комментариях, передача 104 вернет без строк , поскольку пользователь 109 не делает этого.существует в таблице.

...