“存在”相关子查询中递归 CTE 的替代方案?

Ale*_*ith 6 sql recursion sql-server-2005 common-table-expression correlated-subquery

我遇到一种情况,我需要能够查看给定的人是否在用户/经理层次结构中。

我需要能够根据一组规则为一组用户执行此操作(不用担心这一点,只是为了给它一些背景信息)

理想情况下,我想在 where 子句的相关存在子查询中使用递归 CTE。

但这会带来很多问题..

  1. 我认为您根本不能在子查询中使用 CTE。
  2. 我使用兼容模式 80 的 SQL 2005 - 所以我不能使用交叉应用...所以对我来说 UDF 中没有列参数:-(

我想我想做的是:

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).
    )
Run Code Online (Sandbox Code Playgroud)

无论如何,是否可以在兼容模式 80 下使锚点定义动态化?或者另一种方法?

Ale*_*ith 0

我终于到了那里!谢谢大家的帮助。

这是我正在处理的 SQL 的片段。

我只需要改变我的想法,而不是查看 where 子句中的管理器下是否存在用户。我需要将 CTE 视为预过滤器并构建我之前需要的所有详细信息,然后在存在语句之后进行正常过滤(注意,为了简洁起见,我没有包含这些语句)。

RulesUserHierarchy(UserId, ManagerId, PushRuleId, OnlyForSubOrdinates) -- Gets only subordinates for rules created by managers. And all users for those created by admin.
AS
(
    --Anchor Definition
    SELECT
         [Users].[UserId]
        ,[Users].[ManagerId]
        ,[RulesAnchor].[PushRuleId]
        ,[RulesAnchor].[OnlyForSubOrdinates]
    FROM [Users]
        CROSS JOIN [Rules] [RulesAnchor] --assume every user is doing every rule at this point (because the recursive statement has to be the first statement), we'll filter later.
    WHERE (([OnlyForSubOrdinates]) = 0 OR ([OnlyForSubOrdinates] = 1 AND [UserId] = [RulesAnchor].[AddedByUserId]))
    UNION ALL

    --Recursive Member definiation
    SELECT
         [Users].[UserId]
        ,[Users].[ManagerId]
        ,[RulesUserHierarchy].[PushRuleId]
        ,[RulesUserHierarchy].[OnlyForSubOrdinates]
    FROM [Users]
        INNER JOIN [RulesUserHierarchy]
            ON [Users].[ManagerId] = [RulesUserHierarchy].[UserId] --recursive hook 
            AND [RulesUserHierarchy].[OnlyForSubOrdinates] = 1 -- no point recursing if it's for everyone, as the anchor will pull back everything for us.
    WHERE [Users].[UserId] <> [Users].[ManagerId] --don't recurse if the anchor definition matches itself (to avoid an infinate loop).
)       
-- simple statement to test recursion above, will be filtering the inclusions here (e.g. the other mega exists statements)
SELECT [UserId], [ManagerId], [PushRuleId], [OnlyForSubOrdinates] FROM [RulesUserHierarchy]
Run Code Online (Sandbox Code Playgroud)

编辑

我意识到我不需要递归定义中的交叉连接。虽然它不会影响后者的存在语句的结果,但它对性能不利。