【问题标题】:Recursive query rebuild object Graph递归查询重建对象图
【发布时间】:2013-11-04 16:30:29
【问题描述】:

我有 3 个表:用户、组和成员资格。
用户 有 Id 和名称。
也有 Id 和名称。
Membership 有 id、GroupId 和 MemberId

问题是 MemberId 既可以是用户也可以是组。

我想要的是获取用户是否直接属于的所有组。

为此,我使用 CTE,如下所示:

WITH MyGroups AS(
select *,1 as GLevel from [Group] as g where g.id IN (SELECT groupId FROM Membership m where m.memberId='MYID')

UNION ALL

select g.*,2 from [Group] g inner JOIN MyGroups my on my.id=g.id --where g.id IN (SELECT groupId FROM ACLTests.dbo.Membership m where m.groupid=g.id))

Select * from MyGroups

但是我的递归级别超过了 100 级...有人可以帮忙吗?

样本数据:

用户表:
ID---------|标题----------
我的用户 1 |约翰
我的用户2 |狮子座

组表:
ID---------|标题----------
我的 G1 。 . .|组1
我的 G2 。 . .|组2

会员表:
身份证 |组ID |会员编号
01 |我的G1... . .|我的用户1
02 |我的G1... . .|我的G2
03 |我的G2... . .|我的用户2

MyUser1 的预期结果:Group1
MyUser2 的预期结果:Group1,Group2(G2 是 g1 的成员,User2 是 G2 的成员,所以 User2 也是 G1 的成员)

【问题讨论】:

  • 那你的问题是什么?您能否发布一些示例数据和预期输出?
  • @Rachcha 已编辑!看看...

标签: sql sql-server recursion recursive-query


【解决方案1】:

这是您需要的查询。确保你真的需要option (maxrecursion 0),如果是这样,那么也可以在下面的查询中添加它。

    SET NOCOUNT ON
    DECLARE @User TABLE
    (
        id      sysname NOT NULL
        ,title  sysname NOT NULL
    )
    DECLARE @Groups TABLE
    (
        id      sysname NOT NULL
        ,title  sysname NOT NULL
    )
    DECLARE @Membership TABLE
    (
        id      INT NOT NULL
        ,groupid    sysname NOT NULL
        ,memberid   sysname NOT NULL
    )

    INSERT INTO @User( id, title ) SELECT 'myuser1','John' UNION ALL SELECT 'myuser2','Leo'
    INSERT into @Groups( id, title ) SELECT 'myG1','Group1' UNION ALL SELECT 'myG2','Group2'
    INSERT into @Membership( id, groupid, memberid ) SELECT 1,'myG1','myuser1' UNION ALL SELECT 2,'myG1','myG2' UNION ALL SELECT 3,'myG2','myuser2'



    DECLARE @SearchUsergroup sysname='myUser2'
    ;WITH mType(id,title,mType)
    AS
    (
        SELECT id,title,'user' AS mType
        FROM @User
        UNION ALL
        SELECT id,title,'Group' AS mType
        FROM @Groups
    ),
    Ugroups(id,mType,mLevel)
    AS
    (
        SELECT groupid,'Group' as mType, 1 AS mLevel
        FROM @Membership
        WHERE memberid = @SearchUsergroup

        UNION ALL
        SELECT ms.groupid,'Group' as mType, ug.mLevel+1 AS mLevel
        FROM mType mt
        JOIN Ugroups ug
            ON mt.id=ug.id AND ug.mType='Group'
        JOIN @Membership ms
            ON ms.memberid=ug.id
    )
    SELECT id AS GroupID,mLevel AS MembershipLevel
    FROM Ugroups

【讨论】:

    【解决方案2】:

    在查询末尾添加option (maxrecursion 0)

    UPD。

    WITH MyGroups AS (
        select g.id, 1 as GLevel
        from Group as g
        where g.id IN (
            SELECT groupId
            FROM Membership m
            where m.memberId = 'MyUser2'
        )
        UNION ALL
        select m.GroupId, my.GLevel + 1
        from Membership m
        inner JOIN MyGroups my on m.memberId=my.id
    )
    
    Select * from MyGroups
    

    【讨论】:

    • 您没有指定递归查询何时停止。请参阅我的更新答案。
    猜你喜欢
    • 2020-09-04
    • 1970-01-01
    • 2011-01-02
    • 2011-04-25
    • 2010-09-10
    • 2017-01-02
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    相关资源
    最近更新 更多