再帰クエリには、複数の再帰クエリを含めることができますが、それらの再帰クエリが共通の要素を持たず互いに素であることが条件となります。また、再帰クエリには再帰共通テーブル式と非再帰共通テーブル式を混在させることができます。共通テーブル式が 1 つでも再帰的である場合は、RECURSIVE キーワードを含める必要があります。
たとえば、前述のクエリと同じ結果を返す次のクエリは、別の非再帰共通テーブル式を使用して最短ルートの距離を選択しています。2 つめの共通テーブル式の定義は、1 つめの定義からカンマで区切られています。
WITH RECURSIVE trip ( route, destination, previous, distance, segments ) AS ( SELECT CAST( origin || ', ' || destination AS VARCHAR(256) ), destination, origin, distance, 1 FROM travel WHERE origin = 'Kitchener' UNION ALL SELECT route || ', ' || v.destination, v.destination, v.origin, t.distance + v.distance, segments + 1 FROM trip t JOIN travel v ON t.destination = v.origin WHERE v.destination <> 'Kitchener' AND v.destination <> t.previous AND v.origin <> 'Pembroke' AND segments < ( SELECT count(*)/2 FROM travel ) ), shortest ( distance ) AS -- Additional, ( SELECT MIN(distance) -- non-recursive FROM trip -- common table WHERE destination = 'Pembroke' ) -- expression SELECT route, distance, segments FROM trip WHERE destination = 'Pembroke' AND distance < 1.5 * ( SELECT distance FROM shortest ) ORDER BY distance, segments, route; |
非再帰共通テーブル式と同様、再帰式をストアド・プロシージャ内で使用した場合、ローカル変数やプロシージャ・パラメータへの参照を含められます。たとえば、次に定義する best_routes プロシージャは、指定した 2 つの都市の間の最短ルートを特定します。
CREATE PROCEDURE best_routes ( IN initial VARCHAR(10), IN final VARCHAR(10) ) BEGIN WITH RECURSIVE trip ( route, destination, previous, distance, segments ) AS ( SELECT CAST( origin || ', ' || destination AS VARCHAR(256) ), destination, origin, distance, 1 FROM travel WHERE origin = initial UNION ALL SELECT route || ', ' || v.destination, v.destination, -- current endpoint v.origin, -- previous endpoint t.distance + v.distance, -- total distance segments + 1 -- total number of segments FROM trip t JOIN travel v ON t.destination = v.origin WHERE v.destination <> initial -- Don't return to start AND v.destination <> t.previous -- Prevent backtracking AND v.origin <> final -- Stop at the end AND segments -- TERMINATE RECURSION! < ( SELECT count(*)/2 FROM travel ) ) SELECT route, distance, segments FROM trip WHERE destination = final AND distance < 1.4 * ( SELECT MIN( distance ) FROM trip WHERE destination = final ) ORDER BY distance, segments, route; END; |
次の文を実行すると、前述のプロシージャが呼び出されます。
CALL best_routes ( 'Pembroke', 'Kitchener' ); |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |