#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<>.