我尝试使用WITH
创建一个SQL语句,但我无法正确使用。
我得到了以下表格;
群组(身份证,姓名)
1, 'My app'
2, 'Local admins'
3, 'Global admins'
用户(1,姓名)
1, 'Arne'
GroupOwners(GroupId,OwnerType,OwnerId)
1, 'Group', 2
GroupMembers(GroupId,MemberType,MemberId)
2, 'Group', 3
3, 'User', 1
我正在尝试查找Arne
所有的所有群组。在这种情况下,它是My App
。但问题是Local Admins
被设置为所有者。 Global admins
是Local admins
的成员。 Arne
最后是Global admins
的成员。
别介意钻石,它们不正确
嵌套因组而异。 (有些用户直接在GroupOwners中,而其他人可能有一个用户组成为成员)
是否可以用一个SQL语句的母亲来解决?附加约束:Groups
/ Users
在系统的其他地方使用。
答案 0 :(得分:4)
这是递归cte,首先会发现组Arno
是其成员,然后匹配直接或间接包含这些组的所有组。结果最终加入GroupOwners以限制结果。注意:如果Arno
可能是某个组的所有者,但不是其成员,则此查询还需要UNION附加这些组。
declare @UserID int = 1
; with allTheGroups as (
select gm.GroupID
from GroupMembers gm
where gm.MemberType = 'User'
and gm.MemberID = @UserID
union all
select gm.GroupID
from GroupMembers gm
inner join allTheGroups
on gm.MemberID = allTheGroups.GroupID
where gm.MemberType = 'Group'
)
select Groups.*
from Groups
inner join GroupOwners gow
on Groups.ID = gow.GroupID
and gow.OwnerType = 'Group'
inner join allTheGroups a
on gow.OwnerID = a.GroupID
Sql Fiddle with example is here
用于检索直接拥有添加的组的用户的联合示例。需要附加到上面的查询(当然,选择列表调整)。
union
select gow.OwnerID, Users.Name
from GroupOwners gow
inner join Users
on gow.OwnerID = Users.ID
and gow.OwnerType = 'User'
where gow.OwnerID = @UserID
答案 1 :(得分:-2)
是的,您的表格建模不正确。您只需要有两个表。组和管理员(或用户,具体取决于您的方案)。
然后在Admin / User表中存储“Local”或“Global”或名称(Arne)等内容。然后,它只是一个简单的选择或只在两个表之间连接。不需要嵌套/递归。
如果您需要我为您提供ERD或其他解释,请告诉我。