Pregunta

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)

¿Fue útil?

Solución

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

Otros consejos

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top