Sql 锚点和成员具有并集的递归查询

Sql 锚点和成员具有并集的递归查询,sql,sql-server-2008,recursion,Sql,Sql Server 2008,Recursion,我试图进行递归查询,但锚和成员cte都有一个联合。这可能吗?我得到的错误是 公共表表达式“mainMenu”的递归成员具有多个递归引用。 联合的目的是允许角色或个人看到菜单项。如果有更好的办法,我洗耳恭听。蒂亚 with mainMenu (...) as ( select ... from ( -- role select ... from .... and parentID is null

我试图进行递归查询,但锚和成员cte都有一个联合。这可能吗?我得到的错误是

公共表表达式“mainMenu”的递归成员具有多个递归引用。

联合的目的是允许角色或个人看到菜单项。如果有更好的办法,我洗耳恭听。蒂亚

with 
mainMenu (...)
as (
    select ...
    from (
        -- role
        select ...
        from ....
            and parentID is null
        UNION
        --user
        select ...
        from ....
            and parentID is null
    )as cteAnchor
UNION ALL
    select ...
    from (
        -- role
        select ...
        from ....
            inner join  mainMenu on parentID = mainMenu.id
        UNION
        -- user
        select ...
        from ....
            inner join  mainMenu on parentID = mainMenu.id
    )as cteChildren
)

select 
   ...
from 
mainMenu

您不能多次引用
main菜单。这是因为实际上有两个锚表达式,一个用于角色,一个用于用户。有两种方法可以解决这个问题。您可以将查询拆分为两个CTE(一个用于角色,一个用于用户)。像这样:

with
roleMainMenu (...)
as
(
    -- role
    select ...
    from ....
        and parentID is null
    union all
    select ...
    from ....
        inner join  mainMenu on parentID = mainMenu.id
),
userMainMenu (...)
as
(
    -- user
    select ...
    from ....
        and parentID is null
    union all
    select ...
    from ....
        inner join  mainMenu on parentID = mainMenu.id
)
select * from roleMainMenu
union
select * from userMainMenu
或者,您可以事先组合角色和用户锚表达式。我不知道获取子项的查询对于角色和用户菜单项是否都是通用的,否则您可以使用一个锚表达式,该表达式具有角色和用户根项的联合

with mainMenu (...)
as
(
    select root.* from
    (
        -- role roots
        select .. from ... and parentID is null
        union
        -- user roots
        select .. from ... and parentID is null
    ) root
    union all
    select ... from root
    inner join mainMenu on parentID = mainMenu.id
)
select *
from mainMenu

问题似乎是您在使用union all时使用的语法。Union all与join的不同之处在于,它将从一个表中选择的所有行以及从另一个表中选择的所有行合并到一个大表中。当您执行UNIONALL时,您从各个表中选择的列需要对齐,以便sql知道如何将所有数据放入一个表中

相反,存在连接。与union all不同,union all将信息添加为更多数据,而join将更多信息添加到同一行中。联接允许我们将信息连接在一起,并了解有关单个数据点的更多信息

我之所以提到这两个关键字,是因为您基本上结合了UNIONALL和join的语法。您的内部查询需要一个select与第二个from一起执行,并且应该删除表别名。您的内部查询应该更像这样:

select ...
    from (
        -- role
        select ...
        from ....
            and parentID is null
        UNION
        --user
        select ...
        from ....
            and parentID is null
    )
UNION ALL
select ...
    from (
        -- role
        select ...
        from ....
            inner join  mainMenu on parentID = mainMenu.id
        UNION
        -- user
        select ...
        from ....
            inner join  mainMenu on parentID = mainMenu.id
    )

谢谢Jenn,我在实际代码中有一个select,但未能将其转换为psudocode,我更新了OP以反映。至于工会,所有。。。cte递归查询就是这样完成的,除非我遗漏了什么@特拉维斯,我觉得工会很好。您是否尝试过从第二个子查询中删除union?我想问题可能是你参考了两次主菜单。太好了,谢谢。这似乎是我最想要的。现在唯一的问题是,如果锚点有一个角色,但子锚点有一个用户,那么由于内部联接,我无法获取该用户。我想这是我的问题。这回答了我最初的问题,我很感激!