Question

I have 3 tables: User, Group and membership.
User has Id, and Name.
Group also has Id and Name.
Membership has id, GroupId and MemberId

The thing is that MemberId can be both a user AND a group.

What I want is to get all the groups a user belongs directly or not.

To do this I'm using CTE as show below:

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

but i'm going beyond 100 levels of recursion... can anyone help?

Sample Data:

USER TABLE:
ID----------|Title---------
myUser1 |John
myUser2 |Leo

GROUPS TABLE:
ID----------|Title---------
myG1 . . .|Group1
myG2 . . .|Group2

MEMBERSHIP TABLE:
ID | GROUPID | MEMBERID
01 | myG1.. . . .| myUser1
02 | myG1.. . . .| myG2
03 | myG2.. . . .| MyUser2

EXPECTED RESULT FOR MyUser1: Group1
EXPECTED RESULT FOR MyUser2: Group1, Group2 (G2 is a member of g1, and User2 is a member of G2, so User2 is also a member of G1)

Était-ce utile?

La solution

here is the query you need. make sure you really need option (maxrecursion 0) if so then yes add that in below query as well.

    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

Autres conseils

Add option (maxrecursion 0) at the end of your query.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top