Articles
create table HierarchicalT(ID primary key,OyaID) as select 1,null from dual union all select 2, 1 from dual union all select 3, 2 from dual union all select 4, 3 from dual union all select 5, 1 from dual union all select 6, 5 from dual union all select 7, 2 from dual union all select 20,null from dual union all select 21, 20 from dual union all select 22, 21 from dual;
下記のLevel擬似列,sys_connect_by_path関数を使った階層問い合わせと同じ結果を、再帰with句で取得します。
-- 模倣対象の階層問い合わせ select ID,OyaID, Level,sys_connect_by_path(to_char(ID),',') as Path from HierarchicalT start with OyaID is null connect by prior ID = OyaID;
出力結果 ID OyaID Level Path -- ----- ----- --------- 1 null 1 ,1 2 1 2 ,1,2 3 2 3 ,1,2,3 4 3 4 ,1,2,3,4 7 2 3 ,1,2,7 5 1 2 ,1,5 6 5 3 ,1,5,6 20 null 1 ,20 21 20 2 ,20,21 22 21 3 ,20,21,22
-- 再帰with句で模倣 with rec(ID,OyaID,LV,Path) as( select ID,OyaID,1,',' || to_char(ID) from HierarchicalT where OyaID is null union all select b.ID,b.OyaID,a.LV+1, a.Path || ',' || to_char(b.ID) from rec a,HierarchicalT b where a.ID = b.OyaID) select * from rec;
Level擬似列を足し算で模倣し、sys_connect_by_path関数を文字列の連結で模倣してます。
下記のprior演算子,connect_by_root演算子を使った階層問い合わせと同じ結果を、再帰with句で取得します。
-- 模倣対象の階層問い合わせ select ID,OyaID,prior ID as preID, connect_by_root ID as rootID, Level,sys_connect_by_path(to_char(ID),',') as Path from HierarchicalT start with OyaID is null connect by prior ID = OyaID;
出力結果 ID OyaID preID rootID Level Path -- ----- ----- ------ ----- --------- 1 null null 1 1 ,1 2 1 1 1 2 ,1,2 3 2 2 1 3 ,1,2,3 4 3 3 1 4 ,1,2,3,4 7 2 2 1 3 ,1,2,7 5 1 1 1 2 ,1,5 6 5 5 1 3 ,1,5,6 20 null null 20 1 ,20 21 20 20 20 2 ,20,21 22 21 21 20 3 ,20,21,22
-- 再帰with句で模倣 with rec(ID,OyaID,preID,rootID,LV,Path) as( select ID,OyaID,to_number(null),ID,1, ',' || to_char(ID) from HierarchicalT where OyaID is null union all select b.ID,b.OyaID,a.ID,a.rootID,a.LV+1, a.Path || ',' || to_char(b.ID) from rec a,HierarchicalT b where a.ID = b.OyaID) select * from rec;
prior演算子を親ノードの値を使うことで模倣し、connect_by_root演算子を木の根のノードの値を使うことで模倣してます。
create table siblingsT(ID primary key,OyaID) as select 1,null from dual union all select 2, 1 from dual union all select 3, 1 from dual union all select 4, 1 from dual union all select 5, 3 from dual union all select 6, 3 from dual union all select 7, 4 from dual union all select 8, 4 from dual union all select 9, 6 from dual union all select 10, 7 from dual union all select 20,null from dual union all select 21, 20 from dual union all select 22, 20 from dual union all select 23, 21 from dual union all select 24, 21 from dual;
下記のorder siblings byを使った階層問い合わせと同じ結果を、再帰with句で取得します。
-- 模倣対象の階層問い合わせ select connect_by_root ID as treeID, ID,OyaID,Level, sys_connect_by_path(to_char(ID),',') as Path from siblingsT start with OyaID is null connect by prior ID = OyaID order siblings by ID desc;
出力結果
treeID ID OyaID Level Path
------ -- ----- ----- ---------
20 20 null 1 ,20
20 22 20 2 ,20,22
20 21 20 2 ,20,21
20 24 21 3 ,20,21,24
20 23 21 3 ,20,21,23
1 1 null 1 ,1
1 4 1 2 ,1,4
1 8 4 3 ,1,4,8
1 7 4 3 ,1,4,7
1 10 7 4 ,1,4,7,10
1 3 1 2 ,1,3
1 6 3 3 ,1,3,6
1 9 6 4 ,1,3,6,9
1 5 3 3 ,1,3,5
1 2 1 2 ,1,2
-- 再帰with句で模倣 with rec(treeID,ID,OyaID,LV,Path) as( select ID,ID,OyaID,1,',' || to_char(ID) from siblingsT where OyaID is null union all select a.treeID,b.ID,b.OyaID,a.LV+1, a.Path || ',' || to_char(b.ID) from rec a,siblingsT b where a.ID = b.OyaID) search depth first by ID desc set SortKey select * from rec order by SortKey;
search句を使って、再帰withで探索を行った結果に対して、深さ優先探索順で連番を付与し、その連番をソートキーとして使用してます。
|
図でイメージする
Oracle DatabaseのSQL全集 |
||