递归选择

时间:2012-08-28 06:21:40

标签: sql-server database-design

我尝试使用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 adminsLocal admins的成员。 Arne最后是Global admins的成员。

enter image description here

别介意钻石,它们不正确

嵌套因组而异。 (有些用户直接在GroupOwners中,而其他人可能有一个用户组成为成员)

是否可以用一个SQL语句的母亲来解决?附加约束:Groups / Users在系统的其他地方使用。

2 个答案:

答案 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或其他解释,请告诉我。