アプローチは、最初に欠落している階層product
をinfo
考慮して結合し、次に結果を生成することです...階層Product
にinfo
関連するデータがあるため、それらを結合する必要があります。おそらくここが一番苦労した部分だと思います。すべての階層データが 1 か所にあるわけではありません。そのことに気づいたとき、仕事の前に連絡できるようにするための組合の必要性が生まれました。
したがって、結合product
しinfo
て必要な追加の階層データを取得し、これを account テーブルに結合します。これにより、必要なすべての親子関係を含むデータセットが作成されます。
その後、 を使用connect by prior
して階層をトラバースできます。
SELECT a.id_acc, level as lvl
FROM (SELECT id_acc, parent_acc FROM account
UNION
SELECT P.Account_ID, i.account_id FROM info i
INNER JOIN product p
on I.Product_ID=P.Product_ID) A
START WITH A.ID_ACC=76543
CONNECT BY prior a.id_acc=a.parent_acc
これは以下を返します:
Account Lvl
76543 1
18252 2
456452 3
34456 2
456567 2
注: 456452 は 18252 の下に存在するため、階層からの関係が維持されます。76543 には 3 つの子 (18252、34456、456567) があり、18252 には子 456452 があることを意味します。
あなたの質問に関するいくつかの仮定を考えると、これが私が思いつくことができる最善のものだと思います。
フル パスを知る必要がある場合( )、またはsys_connect_by_path
削除する必要があるデータにループがある場合 ( nocycle
) または isLeaf ( connect_by_isLeaf
) で階層内の子のないレコードを表示する必要がある場合は、その他の機能をいくつか追加できます。
SELECT a.id_acc
, level as lvl
, SYS_CONNECT_BY_PATH(ID_Acc, '/') "Path"
, CONNECT_BY_ISLEAF "IsLeaf"
FROM (SELECT id_acc, parent_acc FROM account
UNION
SELECT P.Account_ID, i.account_id
FROM info i
INNER JOIN product p
on I.Product_ID=P.Product_ID) A
START WITH a.id_acc=76543
CONNECT BY nocycle prior a.id_acc=a.parent_acc
これにより、次のような結果になります。
ID_acc lvl Path isLeaf
76543 1 /76543 0
18252 2 /76543/18252 0
456452 3 /76543/18252/456452 1
34456 2 /76543/34456 1
456567 2 /76543/456567 1
機能の完全なリストについては、Oracle Docsを参照してください。
を使用して、データにループがないことの重要性を軽視しましたnocycle
。データにループが存在する場合、結果が正しくない可能性があります。
もう少し作業すれば、to_Show に関係するトップ レベルを特定できます。
select distinct ID_ACC
from (SELECT id_acc, parent_acc FROM account
UNION
SELECT P.Account_ID, i.account_id
FROM info i
inner join product p
on i.product_id=p.product_id) a
where parent_acc is null
connect by prior a.parent_acc = a.id_acc
start with id_acc in (select id from to_show)
それを上記と組み合わせて、ハードコーディングなしで目的の結果を達成します。
SELECT a.id_acc
, level as lvl
, SYS_CONNECT_BY_PATH(ID_Acc, '/') "Path"
, connect_by_isleaf "IsLeaf"
FROM (SELECT id_acc, parent_acc FROM account
UNION
SELECT P.Account_ID, i.account_id
FROM info i
INNER JOIN product p
on i.product_id=p.product_id) a
connect by nocycle prior a.id_acc=a.parent_acc
start with id_acc in
(
select distinct ID_ACC
from (SELECT id_acc, parent_acc FROM account
UNION
SELECT P.Account_ID, i.account_id
FROM info i
inner join product p
on i.product_id=p.product_id) a
where parent_acc is null
connect by prior a.parent_acc = a.id_acc
start with id_acc in (select id from to_show))
ここで行ったのは、サブクエリで start with を使用して to_Show の各レコードのトップ レベル ドメインを取得し、関係を逆にして、ツリーを下ではなく上にクロールし、その個別のトップ レベル ドメインを使用して全体を返すことだけでした。階層; したがって、to_show でノードを表示します。そしてそれが存在する階層全体。

または、重複を排除するための読みやすさとリファクタリングのための CTE (Common Table Expression) として。
with
--Let's combine the hierarchies so they are all in one place.
hsource as (
select id_acc, parent_acc from account
UNION
SELECT P.Account_ID, i.account_id
FROM info i
inner join product p
on i.product_id=p.product_id),
--Now lets get the top domain or root nodes of each item in To_Show
top_domain as (
select distinct id_acc
from (hSource) a
where parent_acc is null --this null compare is actually what tells us it's a root/Top domain! Assumption being all roots have null parent_Acc!
connect by prior a.parent_acc = a.id_acc
start with id_acc in (select id from to_show))
--Now lets use those top domains or root notes to render the hierarchy of each.
SELECT a.id_acc
, level as lvl
, SYS_CONNECT_BY_PATH(ID_Acc, '/') "Path"
, connect_by_isleaf "IsLeaf"
FROM (Select id_acc, parent_acc from hSource) a
connect by nocycle prior a.id_acc=a.parent_acc
start with id_acc in (Select ID_ACC from Top_Domain)
最後に... が null であるという私の仮定parent_Acc
が正しくない場合は、top_domain のクエリを以下に変更する必要があります。 Connect by prior
トップ レベルが null になると想定している場合は、ループ データを取得するため、単純に設定できないa.ID_ACC=a.parent_Acc
したがって、case ステートメントを使用して 2 つのステートメント データを変更し、Parent_ACC is null
a を真のステートメントにするだけです。技術的にはwhere
節はそのままでもいいのですがID_ACC=parent_Acc
、テーマを守りたかったのです。ただし、行は変更する必要がありconnect by prior
ます。上記でデータにループがないと言ったことを思い出してください...まあ、ID_ACC=parent_ACC
それがループを引き起こすとき。つまり、さあ!どうすれば自分の親になれますか? しかし、case ステートメントを使用して処理しました。
with
--Let's combine the hierarchies so they are all in one place.
hsource as (
select id_acc, parent_acc from account
UNION
SELECT P.Account_ID, i.account_id
FROM info i
inner join product p
on i.product_id=p.product_id),
--Now lets get the top domain or root nodes of each item in To_Show
top_domain as (
select distinct a.id_acc
from (hsource) a
--Modification starts here...
where case when a.parent_acc =a.id_Acc then null else a.parent_Acc end is null
connect by prior (case when a.parent_acc=a.id_acc then null else a.parent_Acc end) = a.id_acc
--ends here
start with a.id_acc in (select id from to_show))
--Now lets use those top domains or root notes to render the hierarchy of each.
SELECT a.id_acc
, level as lvl
, SYS_CONNECT_BY_PATH(ID_Acc, '/') "Path"
, connect_by_isleaf "IsLeaf"
FROM (Select id_acc, parent_acc from hSource) a
connect by nocycle prior a.id_acc=a.parent_acc
start with id_acc in (Select ID_ACC from Top_Domain)