У меня есть следующая рекурсивная функция:
ALTER FUNCTION [dbo].[ListAncestors]
(
@Id int
)
RETURNS TABLE
As
RETURN
(
WITH cte As
(
SELECT
UserId,
ManagerId,
Forename,
Surname
FROM
dbo.Users
WHERE
UserId = @Id
UNION ALL
SELECT
T.UserID,
T.ManagerID,
T.Forename,
T.Surname
FROM
cte As C INNER JOIN dbo.Users As T
ON C.UserID = T.ManagerID
)
SELECT
Forename,
Surname
FROM
cte
);
В основном то, что это делает, является возвратами имена всех пользователей ниже указанного пользователя (на основе их идентификатора). То, что я хотел бы сделать, изменяют эту функцию и создают другую функцию, которая делает проверку, если определенный идентификатор пользователя является предком другого.
Я предполагаю, что подпись посмотрела бы что-то как:
CREATE FUNCTION IsAncestor(@Id int, @AncestorId int) RETURNS BIT
Как насчет:
WHILE @Id IS NOT NULL AND @Id <> @AncestorId
BEGIN
SET @Id = (
SELECT ManagerId FROM dbo.Users WHERE UserId = @Id
)
END
RETURN CASE WHEN @Id IS NOT NULL THEN 1 ELSE 0 END
Если мы примем, что исходный CTE берет ID и перечисляет всех "предков" этого ID, я думаю, что следующий запрос проверяет это отношение.
WITH cte As
(
SELECT
UserId,
Forename,
Surname
FROM
dbo.Users
WHERE
UserId = @Id
UNION ALL
SELECT
T.UserID,
T.Forename,
T.Surname
FROM
cte As C INNER JOIN dbo.Users As T
ON C.UserID = T.ManagerID and C.UserID <> @ancestorID
)
SELECT CAST (COUNT(*) as BIT) FROM cte WHERE UserID = @ancestorID
Правда, это немного странно, поскольку в исходной функции человек находится в отношении "предок" с самим собой.
Кстати, я удалил ManagerID из операторов select в CTE, поскольку в нем нет необходимости