SQL查询查找超集角色

时间:2014-07-11 08:45:39

标签: sql ms-access

我们有一个系统,用户从服务目录中选择一个角色,并将角色映射到目标系统中某些组的成员资格。

某些角色的组重叠,而某些角色由另一个角色的完整子集组实现。

后者导致我出现问题。我不知道如何只提取超级套装。

Role Grps
Role1 GrpA
Role1 GrpB
Role1 GrpC
Role2 GrpA
Role2 GrpB
Role3 GrpA
Role3 GrpD

Usr Grps
User1 GrpA
User1 GrpB
User2 GrpA
User2 GrpB
User2 GrpC
User3 GrpA
User3 GrpD
User4 GrpD

需要输出

Usr Role
User1 Role2
User2 Role1
User3 Role3

而不是

Usr Role
User1 Role2
User2 Role1
User2 Role2
User3 Role3

2 个答案:

答案 0 :(得分:1)

对于[tblRoleGrps]

中的测试数据
Role   Grps
-----  ----
Role1  GrpA
Role1  GrpB
Role1  GrpC
Role2  GrpA
Role2  GrpB
Role3  GrpA
Role3  GrpD

和[tblUsrGrps]

Usr    Grps
-----  ----
User1  GrpA
User1  GrpB
User2  GrpA
User2  GrpB
User2  GrpC
User3  GrpA
User3  GrpD
User4  GrpD

我们可以在Access中创建一个名为[qryRoleGrpCounts]的已保存查询,该查询为我们提供了属于每个角色的组的数量

SELECT Role, COUNT(*) AS GrpCount
FROM tblRoleGrps
GROUP BY Role

返回

Role   GrpCount
-----  --------
Role1         3
Role2         2
Role3         2

对于名为[qryUsrGrpCounts]的已保存查询的用户,我们可以做同样的事情

SELECT Usr, COUNT(*) AS GrpCount
FROM tblUsrGrps
GROUP BY Usr

返回

Usr    GrpCount
-----  --------
User1         2
User2         3
User3         2
User4         1

我们还可以创建一个名为[qryUsrRoleMatches]的查询,该查询计算用户与可能所属角色之间的匹配数量

SELECT ug.Usr, rg.Role, COUNT(*) AS MatchCount
FROM tblUsrGrps ug INNER JOIN tblRoleGrps rg ON ug.Grps = rg.Grps
GROUP BY ug.Usr, rg.Role

返回

Usr    Role   MatchCount
-----  -----  ----------
User1  Role1           2
User1  Role2           2
User1  Role3           1
User2  Role1           3
User2  Role2           2
User2  Role3           1
User3  Role1           1
User3  Role2           1
User3  Role3           2
User4  Role3           1

使用这些保存的查询,我们可以构建其他查询以查找用户和角色之间的匹配。例如,列出存在“完全匹配”的实例,意思是......

  

用户和角色(qryUserRoleMatches.MatchCount)之间的匹配数正是该用户的组数(qryUsrGrpCounts.GrpCount)以及相应角色的组数(qryRoleGrpCounts.GrpCount)。

......我们可以使用

SELECT qurm.Usr, qurm.Role
FROM
    (
        qryUsrRoleMatches qurm
        INNER JOIN
        qryUsrGrpCounts qugc
            ON qurm.Usr = qugc.Usr
                AND qurm.MatchCount = qugc.GrpCount
    )
    INNER JOIN
    qryRoleGrpCounts qrgc
        ON qurm.Role = qrgc.Role
            AND qurm.MatchCount = qrgc.GrpCount

返回

Usr    Role 
-----  -----
User1  Role2
User2  Role1
User3  Role3

答案 1 :(得分:0)

在T SQL(SQL Server)查询中可以写成:

with cte_servicecatalogue as
(
select sc1.UserId,
      STUFF(ISNULL((SELECT ', ' + sc.Grps
                FROM servicecatalogue sc
                WHERE sc.UserId = sc1.UserId
                --GROUP BY sc.UserId
               FOR XML PATH (''), TYPE).value('.','VARCHAR(max)'), ''), 1, 2, '') [Groups]
from servicecatalogue sc1
GROUP BY sc1.UserId  
)
,cte_RoleMembership as
( select RM1.Role,
      STUFF(ISNULL((SELECT ', ' + RM.Grps
                FROM RoleMembership RM
                WHERE RM.Role = RM1.Role
                --GROUP BY sc.UserId
               FOR XML PATH (''), TYPE).value('.','VARCHAR(max)'), ''), 1, 2, '') [Groups]
from RoleMembership RM1
GROUP BY RM1.Role  
)
select cte1.UserId, cte2.Role
from cte_servicecatalogue cte1
inner join cte_RoleMembership cte2 on cte1.[Groups] = cte2.[Groups]
order by UserId

检查演示here..