2016-08-29 3 views
2

У меня есть таблица со значениями, аналогичную этойOracle SQL сравнения двух или более строк в одной таблице

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 

Я хочу вывода Grp_IDs, которые имеют 1032 и 1034 (оба) в качестве Role_IDs Например,

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 не имеют как 1032 и 1034, как Role_IDs

Я пробовал используемые внутренние соединения и «того», но не похоже, чтобы получить то, что я хочу.

+1

Возможно, я не понимаю вашу таблицу данных ... Я вижу группу 20, имеющую как 1032, так и 1034 ... – SandPiper

+0

Подсказка: GROUP BY имеет счетчик раздельно. – jarlh

+0

Извините. Я добавил ошибку Grp_ID 20. Я сейчас редактировал свой вопрос. Пожалуйста, проверьте. –

ответ

1
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 
0

Как сказал @jarlh, это сделало бы. Здесь я не использую фильтр на 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 

Выхода

+--------+--------------------+ 
| GRP_ID | COUNT_DIST_ROLE_ID | 
+--------+--------------------+ 
|  20 |     2 | 
|  10 |     2 | 
+--------+--------------------+ 
+0

@ YasarAbdullah - две вещи: во-первых, решение, основанное на «группе», как показано Ustav (и Гордоном в другом ответе), скорее всего, будет намного быстрее, чем решения, использующие JOIN любого типа. И, как сказал Устав, его решение не соответствует строкам «uname» - вам нужно прояснить, каково ваше требование. Если один и тот же GRP_ID имеет как 1032, так и 1034, но для разных 'uname', это все еще нормально, или же группировка должна быть' uname' также? – mathguy

1

Что вам нужно сделать, это соединить таблицу к себе на идентификаторе группы, а затем отфильтровать строки, которые содержат оба ваших роли идентификаторов , Каждая таблица, участвующая в объединении, вносит различную роль. Если вам нужно отфильтровать по 3 значениям, вам понадобится 3 табличных предложения (два соединения).

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 
1

Я хотел бы подойти к этим проблемам с использованием group by и having. В этом случае:

select grp_id 
from tbl 
where role_id in (1032, 1034) 
group by grp_id 
having count(distinct role_id) = 2; 

Я нахожу, что этот метод обобщает множество вариантов вопросов, связанных с множеством заданий.

+0

Да, это выглядит красивее, а план объяснения (по мини-данным, но все же) дешевле, чем самостоятельное соединение. –

1

Просто предложить другой ответ:

SELECT GrpID FROM theTable WHERE roleId = 1032 
INTERSECT 
SELECT GrpID FROM theTable WHERE roleID = 1034 

или

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 

если вам нужен полный текст, как в вашем вопросе ...

, но я не большой поклонник добавления текста, подобного этому в слое представления SQL, должен позаботиться об этом.

+0

Группа (как показано в других ответах) сканирует таблицу только один раз, а не дважды, как это делает любое решение INTERSECT. Эти решения, скорее всего, будут более эффективными. – mathguy

Смежные вопросы