ORACLE 11gR2 SQLの再帰(再帰With句)について 1

いつも一瞬戸惑ってしまう再帰。皆さんはいかがでしょうか。

私の場合、あまり使うことはないので、よく忘れてしまうのですが、
使うことが発生し使いだすと、いつも「便利だな〜」と思います。
メモがてら、再帰についていくつかサンプルを記載したいと思います。

— 部品管理で再帰を利用する。
たとえば、車で考えてみます。
細かく言えば、複雑になるので次のように考えました。

[text] 車
エンジン
エンジン用ねじ
アルミニウム

エンジン用鉄
ハンドル
 ハンドル用ねじ
 ハンドル用鉄
ブレーキペダル
 ブレーキペダル用ねじ
 ブレーキペダル用鉄
アクセルペダル
 アクセルペダル用ねじ
 アクセルペダル用鉄
車体組み立て用ねじ
[/text]

正直こんな単純な構成はほぼないのですが、あくまで再帰の
抽出方法を確認するだけなので、ご了承いただければと思います・・。

上記は、次のようにイメージしてください。
車は、エンジン、ハンドル、ブレーキペダル、アクセルペダル
から成り立っています。
エンジンは、エンジン用ねじと、エンジン用鉄から作られます。

というような読み方で、それぞれの部材の親子関係を示しています。

その次に、上記の関係をDBに登録してみます。
日本語で分かりやすくテーブルを作るとこんな感じでしょうか。

[sql] CREATE TABLE 構成表 (
親 VARCHAR2(100)
,子 VARCHAR2(100)
);

— データも次のように登録します。

INSERT INTO 構成表 (親 , 子)
VALUES(‘車’,’エンジン’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘車’,’ハンドル’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘車’,’ブレーキペダル’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘車’,’アクセルペダル’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘車’,’車体組み立て用ねじ’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘エンジン’,’エンジン用ねじ’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘エンジン’,’エンジン用鉄’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘エンジン用ねじ’,’鉄’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘エンジン用ねじ’,’アルミニウム’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘ハンドル’,’ハンドル用ねじ’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘ハンドル’,’ハンドル用鉄’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘ブレーキべダル’,’ブレーキペダル用ねじ’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘ブレーキペダル’,’ブレーキペダル用鉄’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘アクセルペダル’,’アクセルペダル用ねじ’);

INSERT INTO 構成表 (親 , 子)
VALUES(‘アクセルペダル’,’アクセルペダル用鉄’);
[/sql]

では、階層ごとに出してみましょう。
車がどのような構成で、作られているか
見ることにしましょう。
見やすいように、 親 -> 子 という表現にすることを考えたいと思います。
親が車の構成はどのような感じでしょうか。

まず考え方としては、
http://docs.oracle.com/cd/E16338_01/server.112/b56299/statements_10002.htm#BCEJGIBG
参照にしています。

今回は、再帰With句という ORACLE 11gR2から導入された機能を使います。

[sql] WITH VREC (構成 , 親 , 子) AS
(
SELECT 親 || ‘ -> ‘|| 子 , 親, 子 FROM 構成表
WHERE 親 = ‘車’ AND 子 = ‘エンジン’
UNION ALL
SELECT V.構成 || ‘ -> ‘|| K.子 , K.親, K.子 FROM 構成表 K , VREC V
WHERE V.子 = K.親
)
SELECT 構成 FROM VREC
[/sql]

 

[text] 構成
—————————————————
車 -> エンジン
車 -> エンジン -> エンジン用ねじ
車 -> エンジン -> エンジン用鉄
車 -> エンジン -> エンジン用ねじ -> 鉄
車 -> エンジン -> エンジン用ねじ -> アルミニウム
[/text]

どうでしょうか、下位の構成まですべて出たと思います。
仕組みを簡単に書きたいと思います。
再帰With 句の中で UNION ALL で分かれます。
上の方を、非再帰項といい、下を再帰項といいます。

動きを見ていきましょう。
次の順番で動いていきます。

1.非再帰項を実行します。ここでは、車とエンジンのデータを取得します。
2.再帰項を1.のデータをもとに実行します。エンジンが親となり、そのデータを表示します。
3.再帰項を2.のデータをもとに実行します。エンジン用ねじが親となり、そのデータを表示します。

いかがでしょうか。
再帰は、まだまだ面白いことができます。
今日はこの辺にしてまた、次回追加で説明したいと思います。