Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
olly
Starting Member
5 Posts |
Posted - 2014-07-11 : 04:36:03
|
Hi,We've got a system where users select a role from the service catalogue and the role is mapped to membership of some groups in the target system. There is overlap of the groups across some roles and some roles are fulfilled by a group set that is a complete subset of another role. It's the latter that's causing me a problem. I don't know how to extract the super set only. Role GrpsRole1 GrpARole1 GrpBRole1 GrpCRole2 GrpARole2 GrpBRole3 GrpARole3 GrpDUsr GrpsUser1 GrpAUser1 GrpBUser2 GrpAUser2 GrpBUser2 GrpCUser3 GrpAUser3 GrpDUser4 GrpDOutput required Usr RoleUser1 Role2User2 Role1User3 Role3Rather than Usr RoleUser1 Role2User2 Role1User2 Role2User3 Role3Thanks for your help |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2014-07-11 : 11:25:04
|
Here is a guess. If my guess is not right, can you please define the logic you use to get your expected output in words? DECLARE @RoleGroup TABLE (Role VARCHAR(20), Grp VARCHAR(20))INSERT @RoleGroup VALUES('Role1', 'GrpA'),('Role1', 'GrpB'),('Role1', 'GrpC'),('Role2', 'GrpA'),('Role2', 'GrpB'),('Role3', 'GrpA'),('Role3', 'GrpD')DECLARE @UserGroup TABLE (Usr VARCHAR(20), Grp VARCHAR(20))INSERT @UserGroup VALUES('User1', 'GrpA'),('User1', 'GrpB'),('User2', 'GrpA'),('User2', 'GrpB'),('User2', 'GrpC'),('User3', 'GrpA'),('User3', 'GrpD'),('User4', 'GrpD')SELECT Usr, RoleFROM ( SELECT * ,ROW_NUMBER() OVER (PARTITION BY Usr ORDER BY GrpCount DESC, Role DESC) AS RowNum FROM ( SELECT UG.Usr, RG.Role, COUNT(*) AS GrpCount FROM @UserGroup AS UG INNER JOIN @RoleGroup AS RG ON UG.Grp = RG.Grp GROUP BY UG.Usr, RG.Role ) AS T ) AS T1WHERE RowNum = 1 |
|
|
ScottPletcher
Aged Yak Warrior
550 Posts |
Posted - 2014-07-11 : 13:28:32
|
This may not be the most efficient way, but I believe it's accurate:SELECT rg.Role, ug.Usr, COUNT(ug.Grp) AS Group_CountFROM @UserGroup ugINNER JOIN @RoleGroup rg ON rg.Grp = ug.GrpLEFT OUTER JOIN ( SELECT Role, COUNT(Grp) AS Grp_Count FROM @RoleGroup GROUP BY Role) AS rg_totals ON rg_totals.Role = rg.RoleLEFT OUTER JOIN ( SELECT Usr, COUNT(Grp) AS Grp_Count FROM @UserGroup GROUP BY Usr) AS ug_totals ON ug_totals.Usr = ug.UsrGROUP BY ug.Usr, rg.RoleHAVING MAX(rg_totals.Grp_Count) = MAX(ug_totals.Grp_Count) AND COUNT(ug.Grp) = MAX(ug_totals.Grp_Count)ORDER BY Role, Usr |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2014-07-11 : 15:24:13
|
Basically the same as Lamprey'sWITH cteSource(Usr, [Role], rn, cnt)AS ( SELECT u.Usr, r.[Role], ROW_NUMBER() OVER (PARTITION BY Usr ORDER BY COUNT(*) DESC, [Role] DESC) AS rn, COUNT(*) OVER (PARTITION BY Usr) AS cnt FROM @UserGroup AS u INNER JOIN @RoleGroup AS r ON r.Grp = u.Grp GROUP BY u.Usr, r.[Role])SELECT Usr, [Role]FROM cteSourceWHERE rn = 1 AND cnt >= 2; Microsoft SQL Server MVP, MCT, MCSE, MCSA, MCP, MCITP, MCTS, MCDBA |
|
|
ScottPletcher
Aged Yak Warrior
550 Posts |
Posted - 2014-07-11 : 18:31:11
|
With the same core logic difference.If you add these rows to the User table:('User5', 'GrpA'),('User5', 'GrpB'),('User5', 'GrpC'),('User5', 'GrpD')then check the results, you'll see what I mean.I'm not sure which method olly considers more accurate. |
|
|
olly
Starting Member
5 Posts |
Posted - 2014-07-12 : 02:24:54
|
Hi,Thanks for the replies guys, I'll look into them on Monday when I'm back at work.I didn't mention this is in MS Access so I can implement ScottPlatcher's reply but probably not the other.I'll try that in SQL server too though just to get my head round it.My gut/totally off-the-cuff feel is that it's a harder problem than you think and that maybe I haven't given enough data or examples but as I said it'll have to wait till Monday now. |
|
|
|
|
|
|
|