Reputation: 1171
I have a table of UserIds and rolenames.
For example:
UserId Rolename
1 Admin
1 Editor
1 Other
2 Admin
3 Other
I want to return a single row per user containing UserId, IsAdmin, IsEditor
, where the latter two columns are booleans representing whether or not the user has the "Admin" role or "Editor" role.
From the above example I would get the following output:
UserId IsAdmin IsEditor
1 True True
2 True False
3 False False
Any thoughts? I've been trying all sorts of things with aggregate functions in group by, sub selects etc., but I'm just not getting it.
Upvotes: 1
Views: 120
Reputation: 3708
users :
UserId UserName
1 amir
2 john
3 sara
user roles :
UserId RoleName
1 Admin
1 Editor
2 Editor
query :
select UserId ,
(select count(UserRoles.UserId) from userRoles where userRoles.UserId=users.UserId and RoleName='Admin' ) as IsAdmin ,
(select count(userRoles.UserId) from userRoles where userRoles.UserId=users.UserId and RoleName='Editor' ) as IsEditor
from users;
result :
UserId IsAdmin IsEditor
1 1 1
2 0 1
3 0 0
Upvotes: 1
Reputation: 47454
One possible solution:
SELECT
UserId,
CASE WHEN EXISTS (SELECT * FROM #UserRoles A WHERE A.UserId = UR.UserId AND A.Rolename = 'Admin') THEN 'True' ELSE 'False' END AS IsAdmin,
CASE WHEN EXISTS (SELECT * FROM #UserRoles E WHERE E.UserId = UR.UserId AND E.Rolename = 'Editor') THEN 'True' ELSE 'False' END AS IsEditor
FROM
UserRoles UR
GROUP BY
UR.UserId
Whether or not that's valid syntax depends on what type of SQL you're using - Oracle? You didn't specify.
Another possible solution:
SELECT
U.UserId,
CASE WHEN A.UserId IS NOT NULL THEN 'True' ELSE 'False' END AS IsAdmin,
CASE WHEN E.UserId IS NOT NULL THEN 'True' ELSE 'False' END AS IsEditor
FROM
(
SELECT DISTINCT
UserId
FROM
UserRoles UR
) U
LEFT OUTER JOIN UserRoles A ON A.UserId = U.UserId AND A.Rolename = 'Admin'
LEFT OUTER JOIN UserRoles E ON E.UserId = U.UserId AND E.Rolename = 'Editor'
These solutions also both assume that you will never have multiple rows for the same user id with the same exact role name. For example, User ID 1 with Admin twice in the table.
Upvotes: 2
Reputation: 2163
There are a few ways to do it. Assuming that your table is named USERROLE, this works with your sample data on DB2 for i 6.1:
WITH adminrole(UserId, RoleName) AS (
SELECT UserId, RoleName FROM userrole WHERE RoleName = 'Admin'),
editorrole(UserId, RoleName) AS (
SELECT UserId, RoleName FROM userrole WHERE RoleName = 'Editor'),
groupid(UserId) AS (
SELECT UserId FROM userrole GROUP BY UserId)
SELECT groupid.UserId,
CASE WHEN adminrole.RoleName = 'Admin'
THEN 'True' ELSE 'False' END AS IsAdmin,
CASE WHEN editorrole.RoleName = 'Editor'
THEN 'True' ELSE 'False' END AS IsEditor
FROM groupid LEFT OUTER JOIN adminrole
ON groupid.UserId = adminrole.UserId
LEFT OUTER JOIN editorrole
ON groupid.UserId = editorrole.UserId
Output from STRSQL looks like:
....+....1....+....2....+....3...
USERID ISADMIN ISEDITOR
1 True True
2 True False
3 False False
******** End of data ********
The USERID column is defined as INTEGER in my test data.
Should work anywhere from V5R3 up to current. Change the table name from USERROLE to whatever your table name is.
There are various changes that can be made, but more info would be needed to know what would really be a good structure.
Upvotes: 0
Reputation: 578
with data as (
select 1 userid, 'Admin' rolename from dual union all
select 1 userid, 'Editor' rolename from dual union all
select 1 userid, 'Other' rolename from dual union all
select 2 userid, 'Admin' rolename from dual union all
select 3 userid, 'Other' rolename from dual
)
select userid,
max(case when rolename = 'Admin' then 'True' else 'False' end) isadmin,
max(case when rolename = 'Editor' then 'True' else 'False' end) iseditor ,
max(case when rolename = 'Other' then 'True' else 'False' end) isother
from data
group by userid
OUTPUT:
USERID ISADMIN ISEDITOR ISOTHER
---------- ------- -------- -------
1 True True True
2 True False False
3 False False True
Upvotes: 1