我有一种情况,我需要能够查看给定的人是否在用户/经理层次结构中。
我需要能够根据一组规则为一组用户执行此操作(不要担心这一点,只是为了给它一些上下文)
理想情况下,我想在 where 子句的相关存在子查询中使用递归 CTE。
但这会带来很多问题..
我想我想做的是:
WITH UserHierarchy(UserId, ManagerId)
AS
(
--Anchor Definition
SELECT [UserId], [ManagerId] FROM [Users] WHERE [ManagerId] = [Rules].[RuleAddedByUserId] -- this needs to bind to an outer query....
UNION ALL
--Recursive Member definiation
SELECT [Users].[UserId], [Users].[ManagerId] FROM [Users]
INNER JOIN [UserHierarchy] ON [Users].[ManagerId] = [UserHierarchy].[UserId]
WHERE [Users].[UserId] <> [Users].[ManagerId] --don't recurse if the anchor definition matches itself (to avoid an infinate loop).
)
无论如何,是否可以在兼容模式 80 中使 anchor 定义动态?或者另一种方法?
最佳答案
一种方法是创建一个递归 CTE,对于每个用户,树中该用户的每个祖先都有一行。然后您可以使用 CTE 过滤祖先。例如,对于这棵树:
Bob
|-Alice
|-Jim
CTE 将返回如下内容:
User Ancestor Level
---- -------- -----
Bob NULL 1
Alice Bob 1
Jim Alice 1
Jim Bob 2
Level
列最终不是很重要,但我发现它在我编写查询时很有帮助。这是一个示例脚本,用于标识层次结构中 Alice 下的所有用户:
CREATE TABLE Users(
UserId int NOT NULL PRIMARY KEY,
Name nvarchar(25),
ManagerId int
);
GO
INSERT INTO Users (UserId, Name, ManagerId)
SELECT 1, 'Bob', NULL UNION ALL
SELECT 2, 'Steve', 1 UNION ALL
SELECT 3, 'Chris', 2 UNION ALL
SELECT 4, 'Alice', 1 UNION ALL
SELECT 5, 'Roger', 4 UNION ALL
SELECT 6, 'Tony', 5;
GO
WITH all_ancestors AS (
SELECT
u.UserId,
u.Name,
u.ManagerId AS AncestorId,
1 AS level
FROM
Users AS u
UNION ALL
SELECT
alla.UserId,
alla.Name,
u.ManagerId AS AncestorId,
alla.level + 1
FROM
all_ancestors AS alla
INNER JOIN
Users AS u
ON
alla.AncestorId = u.UserId
)
SELECT
u.*
FROM
Users AS u
INNER JOIN
all_ancestors AS a
ON
u.UserId = a.UserId
WHERE
a.AncestorId = 4; -- Alice
GO
DROP TABLE Users;
GO
关于sql - 'exists' 相关子查询中递归 CTE 的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8340423/