SQL-запрос для получения правильных данных

#sql #oracle

#sql #Oracle

Вопрос:

Я хочу получить данные TABLE2 из данных TABLE1.

Если flg есть 1 , cusId1 и cusId2 это один и тот же человек.

Например, если 1 amp; 2 — одно и то же лицо и 2 amp; 3 — одно и то же лицо, 1 amp; 3 — одно и то же лицо.

ТАБЛИЦА1

cusId1 cusId2 flg
1 2 1
2 3 1
3 4 2
5 1 2
6 7 1
7 8 1
8 6 1

ТАБЛИЦА2

CusId mainId
1 1
2 1
3 1
4 4
5 5
6 6
7 6
8 6

Я думал о том, какой SQL использовать, но не могу придумать.
должен ли я использовать рекурсивный SQL?
Тип базы данных — Oracle12c.

 
WITH VREC (TABLE1 , cusId1  , cusId2) AS
(
   SELECT cusId1 || ' -> '|| cusId2 , cusId1, cusId2 FROM TABLE1
   WHERE cusId1 = '1' AND cusId2 = '2'
UNION ALL
   SELECT V.TABLE1 || ' -> '|| K.cusId2 , K.cusId1, K.cusId2 FROM TABLE1 K , VREC V
   WHERE V.cusId1 = K.cusId1
   AND flg = '1'
)
SELECT TABLE1 FROM VREC

# TABLE1
# 1 -> 1
# 1 -> 2 -> 3
 

Пожалуйста, дайте мне знать, если у вас есть хорошая идея.

Ответ №1:

Это довольно сложно, потому что у вас есть циклический граф. Вы можете справиться с этим, используя рекурсивный CTE и отслеживая посещенные узлы:

 with alledges as (
      select cusid1, cusid2
      from t
      where flg = 1
      union all
      select cusid2, cusid1
      from t
      where flg = 1
      union all
      (select cusid1, cusid1
       from t
       where not exists (select 1 from t t2 where t2.flg = 1 and t.cusid1 in (t2.cusid1, t2.cusid2))
       union
       select cusid2, cusid2
       from t
       where not exists (select 1 from t t2 where t2.flg = 1 and t.cusid2 in (t2.cusid1, t2.cusid2))
      )
     ),
     cte (parentid, childid, visited) as (
      select distinct cusid1, cusid1, ',' || cusid1 || ','
      from alledges
      union all
      select cte.parentid, ae.cusid2, cte.visited || ae.cusid2 || ','
      from cte join
           alledges ae
           on cte.childid = ae.cusid1
      where cte.visited not like '%,' || ae.cusid2 || ',%'
     )
select childid, min(parentid) 
from cte
group by childid
order by childid;
 

Вот скрипка db<>.