2016-03-14 2 views
1

У меня есть таблица соответствия клиентов, которая содержит пары идентификаторов клиентов, как показано ниже.Группирование пар записей в Oracle SQL

PAIR_ID  CUST_ID MATCH_CUST_ID 
12345  800001 900001 
12346  800002 900001 
12347  800003 900001 
12348  800004 900002 
12349  900003 900004 
12350  900004 900005 
12351  900004 900006 

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

Например,

Группа 1:

800001 
800002 
800003 
900001 

Группа 2:

800004 
900002 

Группа 3:

900003 
900004 
900005 
900006 

Есть простой способ сделать это убедитесь, что я не упускаю любая пара, которая должна содержаться в группе?

+0

Я бы сказал, что не будет простого способа, если один и тот же идентификатор может встречаться в 'CUST_ID' и в' MATCH_CUST_ID' в разных строках. –

+0

Укажите точное условие, которое необходимо выполнить, чтобы рассмотреть два идентификатора ***, связанных ***. –

+0

Его случай выведения ссылки. Если A связано с B и B связано с C, поэтому A также связан с C. – Reggie1977

ответ

1

Удар должен сделать трюк:

with cpair (PAIR_ID, CUST_ID, MATCH_CUST_ID) 
as 
(select 12345, 800001, 900001 from dual 
union all 
select 12346, 800002, 900001 from dual 
union all 
select 12347, 800003, 900001 from dual 
union all 
select 12348, 800004, 900002 from dual 
union all 
select 12349, 900003, 900004 from dual 
union all 
select 12350, 900004, 900005 from dual 
    union all 
select 12351, 900004, 900006 from dual) , 
tree (mainid, custid, matchcustid, path) as 
(select cust_id, cust_id, match_cust_id, to_char(pair_id) 
from cpair 
union all 
select mainid, 
    case when (p.CUST_ID = t.matchcustid) then p.CUST_ID 
     when (p.MATCH_CUST_ID = t.matchcustid) then p.match_CUST_ID 
     when ( p.cust_id = t.custid) then p.CUST_ID 
     when (p.match_cust_id = t.custid) then p.match_CUST_ID 
    end, 
    case when (p.CUST_ID = t.matchcustid) then p.MATCH_CUST_ID 
     when (p.MATCH_CUST_ID = t.matchcustid) then p.CUST_ID 
     when ( p.cust_id = t.custid) then p.MATCH_CUST_ID 
     when (p.match_cust_id = t.custid) then p.CUST_ID 
    end, 
    t.path || '-' || to_char(p.PAIR_ID) 
from tree t 
join cpair p 
on 
(p.CUST_ID = t.matchcustid 
or p.MATCH_CUST_ID = t.matchcustid 
or p.cust_id = t.custid 
or p.match_cust_id = t.custid 
) 
and instr(path, pair_id) < 1 
), 
distinctTree as 
(
    select distinct mainid, matchcustid 
    from tree 
    union all 
    select distinct mainid, mainid 
    from tree 
    order by mainid), 
treeGroup as (
    select mainid, listagg(matchcustid, ',') within group (order by matchcustid) custList 
    from distinctTree 
    group by mainid) 
    select distinct custlist from treeGroup 

Результат:

CustList 
------------- 
800004,900002 
900003,900004,900005,900006 
800001,800002,800003,900001 

Запрос идет рекурсивно через дерево отношений с клиентами и создает список связанных клиентов для каждого клиента. После этого список связанного клиента изменяется на строку, которая используется для группировки. От группировки мы можем видеть, что клиенты принадлежат к какой группе.

+0

Впечатляющее решение! –

+0

Фантастический. Спасибо за это. Работает. – Reggie1977

0
with T0 as (--input data 
select 12345 as pair_id,800001 as cust_id,900001 as mutch_cust_id from dual 
union all 
select 12346,  800002, 900001 from dual 
union all 
select 12347,  800003, 900001 from dual 
union all 
select 12348,  800004, 900002 from dual 
union all 
select 12349 ,  900003, 900004 from dual 
union all 
select 12350,  900004, 900005 from dual 
union all 
select 12351,  900004, 900006 from dual 

), 
T1 as (--input data + mirror 
select pair_id, cust_id, mutch_cust_id, 'input' as sign from t0 
union all 
select pair_id, mutch_cust_id, cust_id, 'mirror' from t0 
) 
--result 
select max(CONNECT_BY_ROOT x.pair_id) "group", x.cust_id 
from T1 x 
start with x.sign='input' 
connect by nocycle prior x.cust_id=x.mutch_cust_id 
group by x.cust_id 
order by 1,2 
Смежные вопросы