該当する結果がありません

一致する検索結果がありませんでした

お探しのものを見つけるために、以下の項目を試してみてください。

  • キーワード検索のスペルを確認してください。
  • 入力したキーワードの同義語を使用してください。たとえば、「ソフトウェア」の代わりに「アプリケーション」を試してみてください。
  • 下記に示すよく使用される検索語句のいずれかを試してみてください。
  • 新しい検索を開始してください。

 

急上昇中の質問

connect by NoCycle

再訪問を防いだ階層問い合わせ

cycleというのは英語で、「ひと巡り、一巡、周期」という意味です。

connect by NoCycleを使うと、経路上で訪問済であるノードへの再訪問を防いだ階層問い合わせを行うことができます。

connect by NoCycleはデータ構造が有向グラフや無向グラフである場合によく使われます。

create table NoCycleSample(ID primary key,NextID) as
select  1,   2 from dual union all
select  2,   3 from dual union all
select  3,null from dual union all
select 50,  51 from dual union all
select 51,  52 from dual union all
select 52,  50 from dual;  

木の根となる条件を、ID = 1

親子条件を、親のNextID = 子のID

として階層問い合わせを行います。

-- 閉路のない階層問い合わせ
select ID,NextID,Level,
sys_connect_by_path(to_char(ID),',') as Path
  from NoCycleSample
start with ID = 1
connect by prior NextID = ID;  
出力結果
ID  NextID  Level  Path
--  ------  -----  ------
 1       2      1  ,1
 2       3      2  ,1,2
 3    null      3  ,1,2,3  

次は、木の根となる条件を、ID = 50

親子条件を、親のNextID = 子のID

として階層問い合わせを行います。


-- 閉路のある階層問い合わせ1
select ID,NextID,Level,
sys_connect_by_path(to_char(ID),',') as Path
  from NoCycleSample
start with ID = 50
connect by prior NextID = ID; 

出力結果  ERROR: ORA-01436: ユーザー・データでCONNECT BYのループが発生しました  

start with ID = 50によって、ID=50の行を根とした階層問い合わせが行われますが、

ID=50の行の子供が、ID=51の行。

ID=51の行の子供が、ID=52の行。

ID=52の行の子供が、ID=50の行。

といったデータになっていて、経路上で訪問済であるノードへの再訪問が行われるため、

ORA-01436が発生してしまいます。

このように閉路のあるデータ構造の時には、connect by NoCycleを使うと、親子関係があるけど経路上で訪問済であるノードへの再訪問を防いだ階層問い合わせを行うことができます。

connect by NoCycleは、connect_by_IsCycle疑似列と併用できます。

connect_by_IsCycle疑似列は、経路上で訪問済であるノードを子供に持てば1、そうでなければ0となります。


-- 閉路のある階層問い合わせ2
select ID,NextID,Level,
sys_connect_by_path(to_char(ID),',') as Path,
connect_by_IsCycle as IsCycle
  from NoCycleSample
start with ID = 50
connect by NoCycle prior NextID = ID; 

出力結果
ID  NextID  Level  Path       IsCycle
--  ------  -----  ---------  -------
50      51      1  ,50              0
51      52      2  ,50,51           0
52      50      3  ,50,51,52        1  

connect by NoCycleとconnect_by_IsCycle疑似列のイメージは、下記となります。

赤色のバツ印で、親子関係があるけど経路上で訪問済であるノードへの再訪問を防いでます。

connect by NoCycleとconnect_by_IsCycle疑似列のイメージ

▲ ページTOPに戻る

connect_by_IsCycle疑似列

訪問済ノードを子供に持つかを表す

移動先を複数持てる有向グラフを対象とした階層問い合わせで、connect_by_IsCycle疑似列を使ってみます。

create table IsCycleSample(
ID primary key,NextID1,NextID2) as
select 1,   2,   4 from dual union all
select 2,   3,null from dual union all
select 3,   4,null from dual union all
select 4,   5,null from dual union all
select 5,   2,null from dual;

木の根となる条件を、ID = 1

親子条件を、親のNextID1 = 子のID または 親のNextID2 = 子のID

として階層問い合わせを行い、

(同じノードへ再訪問しない)各ノードまでの経路を列挙します。


-- connect_by_IsCycle擬似列の使用例
select ID,Level,sys_connect_by_path(to_char(ID),',') as Path,
connect_by_IsCycle as IsCycle
  from IsCycleSample
start with ID = 1
connect by NoCycle ID in(prior NextID1,prior NextID2);  
出力結果
ID  Level  Path        IsCycle
--  -----  ----------  -------
 1      1  ,1                0
 2      2  ,1,2              0
 3      3  ,1,2,3            0
 4      4  ,1,2,3,4          0
 5      5  ,1,2,3,4,5        1
 4      2  ,1,4              0
 5      3  ,1,4,5            0
 2      4  ,1,4,5,2          0
 3      5  ,1,4,5,2,3        1 

上記の結果から、connect_by_IsCycle疑似列は、経路上で訪問済であるノードを子供に持てば1、そうでなければ0となることが確認できます。

SQLのイメージは下記となります。有向グラフをイメージしてます。

SQLのイメージ

▲ ページTOPに戻る