【问题标题】:Recursive query where anchor and member have unions锚点和成员有联合的递归查询
【发布时间】:2014-08-27 23:44:03
【问题描述】:

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

Recursive member of a common table expression 'mainMenu' has multiple recursive references.

联合的目的是允许菜单项按角色或个人可见。如果有更好的方法,我会全力以赴。蒂亚!

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

【问题讨论】:

    标签: sql sql-server-2008 recursion


    【解决方案1】:

    您不能多次引用mainMenu。这是因为您实际上有两个锚表达式,一个用于角色,一个用于用户。有两种方法可以解决此问题。您可以将查询拆分为两个 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
    

    【讨论】:

    • 太好了,谢谢。这似乎主要是我所追求的。现在唯一的问题是,如果锚有角色但孩子有用户,由于内部连接,我没有得到用户。我认为这是我的问题。这回答了我最初的问题,我很感激!
    【解决方案2】:

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

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

    我提出这两个关键字是因为您基本上结合了 union all 和 join 的语法。您的内部查询需要选择与第二个 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,我在实际代码中有一个选择,但未能将其转换为伪代码,我更新了 OP 以反映。至于 union all ......这就是 cte 递归查询的完成方式,除非我遗漏了什么? technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx
    • @Travis,工会在我看来都是对的。您是否尝试过从第二个子查询中删除联合?我认为问题可能是您两次引用 mainMenu。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    相关资源
    最近更新 更多