I have a SQL problem which I cannot solve
There are 2 tables mms
and mms_mv
which are linked via object_id
.
The mms_mv
is a multivalue table and the content is group memberships and group manager which also can be an other group.
This runs on SQL Server
mms
:
|object_id|attribute_type|objectSid|
| 1 |user | a |
| 2 | group | b |
| 3 | group | c |
| 4 | group | d |
| 5 | group | f
mms_mv
:
|object_id|attribute_name|reference_id|
| 2 | member | 1 |
| 3 | manager | 1 |
| 4 | manager | 2 |
I am trying to find out which groups a user can manage either directly or indirectly via nested groups.
In the example above the user (1) is member of group Number 2 and group 2 is Manager of group 4 user 1 is manager of group 3 directly.
Which groups can be managed by the user?
So the output I need is group 3 and 4
select
accountname, objectsid, mms1.reference_id as ManagerID,
mms2.object_id
from
dbo.mms_mv_link as mms1 with (nolock)
inner join
dbo.mms_metaverse as mms2 with (nolock) on mms1.object_id = mms2.object_id
where
mms2.object_type ='group'
and mms1.attribute_name = 'manager'
and mms1.reference_id in (1, 3)
This is the best I came up with to find out which of all Group id's and user id I submitted are Manager of a Group. I used an other lookup to get the groups a user is in.
My problem are the nested groups, by long thinking and googling I am not sure if it is even possible to create such a query.
I can find out all groups a user is member of, but I also need the Groups in which these groups are members.
Well I am happy if anyone has some ideas or hints for me to figure this one out.
I am even happy if you have a recommendation for a good sql book which covers such complex queries.
Thank you all for helping me.
I think that the following recursive CTE will give you what you want:
;WITH cte AS
(
SELECT m2.object_id AS groupID, m2.attribute_name
FROM @mms AS m1
INNER JOIN @mms_mv AS m2 ON m1.object_id = m2.reference_id
INNER JOIN @mms m3 ON m2.object_id = m3.object_id
WHERE m1.attribute_type = 'user' AND m3.attribute_type = 'group'
UNION ALL
SELECT m.object_id AS groupID, m.attribute_name
FROM cte AS c
INNER JOIN @mms_mv AS m ON c.groupID = m.reference_id
)
SELECT *
FROM cte
WHERE attribute_name <> 'member'
The so-called 'anchor' query of the CTE returns all groups that every user either manages or is member of. Using recursion we get all other groups managed by either the groups of the original set or by any 'intermediate' set.
With these data as input:
DECLARE @mms TABLE (object_id INT, attribute_type VARCHAR(10), objectSid VARCHAR(10))
DECLARE @mms_mv TABLE (object_id INT, attribute_name VARCHAR(10), reference_id INT)
INSERT @mms VALUES
( 1, 'user', 'a'),
( 2, 'group', 'b'),
( 3, 'group', 'c'),
( 4, 'group', 'd'),
( 5, 'group', 'f')
INSERT @mms_mv VALUES
( 2, 'member', 1),
( 3, 'manager', 1),
( 4, 'manager', 2),
( 5, 'manager', 3)
the above query yields the following output:
groupID attribute_name
----------------------
3 manager
5 manager
4 manager
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.