Reputation: 73
I have a table with values similar to this
Uname | Grp_ID | Role_ID
---------------------
usr1 | 10 | 1032
usr1 | 10 | 1034
usr1 | 20 | 1032
usr1 | 20 | 1034
usr1 | 30 | 1032
usr1 | 40 | 1032
usr1 | 50 | 1034
usr1 | 50 | 1034
usr1 | 60 | 1018
usr1 | 70 | 1057
I want output Grp_IDs which have 1032 and 1034 (both) as the Role_IDs For example,
Grp_ID 10 has 1032 and 1034 as ROle_IDs
Grp_ID 20 has 1032 and 1034 as ROle_IDs
Grp_ID 30, 40, 50, 60 ,70 do not have both 1032 and 1034 as Role_IDs
I have tried used inner joins and 'having' but don't seem to get what I want.
Upvotes: 4
Views: 2177
Reputation: 8121
As @jarlh told, this would do. Here I am not using filter on uname
with tbl (Uname,Grp_ID,Role_ID) as
( select 'usr1',10,1032 from dual union all
select 'usr1',10,1034 from dual union all
select 'usr1',20,1032 from dual union all
select 'usr1',20,1034 from dual union all
select 'usr1',30,1032 from dual union all
select 'usr1',40,1032 from dual union all
select 'usr1',50,1034 from dual union all
select 'usr1',50,1034 from dual union all
select 'usr1',60,1018 from dual union all
select 'usr1',70,1057 from dual
)
--Query
select grp_id
,count(distinct role_id) as count_dist_role_id
from tbl
where Role_ID in (1032,1034)
group by grp_id
having count(distinct role_id)=2
Output
+--------+--------------------+
| GRP_ID | COUNT_DIST_ROLE_ID |
+--------+--------------------+
| 20 | 2 |
| 10 | 2 |
+--------+--------------------+
Upvotes: 0
Reputation: 35343
Just to offer a different answer:
SELECT GrpID FROM theTable WHERE roleId = 1032
INTERSECT
SELECT GrpID FROM theTable WHERE roleID = 1034
or
SELECT 'Grp_ID '|| GRPID ||' has 1032 and 1034 as Role_IDs'
FROM theTable
WHERE roleId = 1032
INTERSECT
SELECT 'Grp_ID '|| GRPID ||' has 1032 and 1034 as Role_IDs'
FROM theTable
WHERE roleID = 1034
if you need the full text as in your question...
but I'm not a big fan of adding text like this in the SQL presentation layer should take care of it.
Upvotes: 1
Reputation: 1270873
I like to approach these problems using group by
and having
. In this case:
select grp_id
from tbl
where role_id in (1032, 1034)
group by grp_id
having count(distinct role_id) = 2;
I find that this method generalizes to many variations of set-within-sets questions.
Upvotes: 2
Reputation: 48730
What you need to do is join the table to itself on group id, and then filter for rows that contain both of your role ids. Each table involved in the join contributes a different role. If you needed to filter on 3 values, then you'd need 3 table clauses (two joins).
WITH thetable AS (
SELECT 10 grpid, 1032 roleid FROM dual UNION ALL
SELECT 10 grpid, 1034 roleid FROM dual UNION ALL
SELECT 20 grpid, 1032 roleid FROM dual UNION ALL
SELECT 20 grpid, 1034 roleid FROM dual UNION ALL
SELECT 30 grpid, 1032 roleid FROM dual UNION ALL
SELECT 40 grpid, 1032 roleid FROM dual UNION ALL
SELECT 50 grpid, 1034 roleid FROM dual UNION ALL
SELECT 50 grpid, 1034 roleid FROM dual UNION ALL
SELECT 60 grpid, 1018 roleid FROM dual UNION ALL
SELECT 70 grpid, 1057 roleid FROM dual
)
SELECT t1.grpid, t1.roleid, t2.roleid
FROM thetable t1
JOIN thetable t2 ON t1.grpid = t2.grpid
WHERE t1.roleid = 1032 AND t2.roleid = 1034;
groupid roleid roleid_1
10 1032 1034
20 1032 1034
Upvotes: 1
Reputation: 2906
Select t1.uname, t2.grp_id, t1.role_id from table_name t1
left join table_name t2 on t1.grp_is = t2.grp_id
Where t1.role_id = 1032 and t2.role_id = 1034
Upvotes: 1