递归查询重建对象Graph

时间:2013-10-25 13:55:16

标签: sql sql-server recursion recursive-query

我有3个表:用户,组和成员。
用户有Id和姓名 群组也有身份证和姓名 会员有id,GroupId和 MemberId

MemberId 可以是用户 AND 一个群组。

我想要的是让用户所属的所有群组直接或不

要做到这一点,我使用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级递归......任何人都可以帮忙吗?

示例数据:

USER TABLE:
ID ---------- |标题---------
myUser1 |约翰
myUser2 |狮子座

组表:
ID ---------- |标题---------
myG1。 。 。|组别1
myG2。 。 。|组2

会员表:
ID | GROUPID | MEMBERID
 01 | myG1 .. 。 。|为MyUser1
 02 | myG1 .. 。 。| myG2
 03 | myG2 .. 。 。| MyUser2

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

2 个答案:

答案 0 :(得分: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

enter image description here

答案 1 :(得分:0)

在查询结尾处添加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