トップページに戻る    次の再帰with句のサンプルへ    前の再帰with句のサンプルへ

再帰with句07 最短距離問題

SQLパズル

travelテーブル
origin        destination   distance
------------  ------------  --------
バリー        トロント            90
トロント      バリー              90
キッチナー    トロント           105
トロント      キッチナー         105
バリー        ハンツビル         125
ハンツビル    バリー             125
ハンツビル    ノースベイ         130
ノースベイ    ハンツビル         130
ペンブローク  オタワ             150
オタワ        ペンブローク       150
キッチナー    バリー             155
バリー        キッチナー         155
トロント      ベルビル           190
ベルビル      トロント           190
ノースベイ    ペンブローク       220
ペンブローク  ノースベイ         220
ベルビル      オタワ             230
オタワ        ベルビル           230
ベルビル      ペンブローク       230
ペンブローク  ベルビル           230
ハンツビル    ペンブローク       245
ペンブローク  ハンツビル         245

キッチナーからペンブロークまでの経路のリストと、距離の合計を、
全て列挙する



出力結果
距離  ルート
----  -------------------------------------------------------------
 525  キッチナー,トロント,ベルビル,ペンブローク
 525  キッチナー,バリー,ハンツビル,ペンブローク
 565  キッチナー,トロント,バリー,ハンツビル,ペンブローク
 630  キッチナー,バリー,ハンツビル,ノースベイ,ペンブローク
 665  キッチナー,バリー,トロント,ベルビル,ペンブローク
 670  キッチナー,トロント,バリー,ハンツビル,ノースベイ,ペンブローク
 675  キッチナー,トロント,ベルビル,オタワ,ペンブローク
 815  キッチナー,バリー,トロント,ベルビル,オタワ,ペンブローク


データ作成スクリプト

create table travel(
origin      varchar2(18),
destination varchar2(18),
distance    number);

insert into travel values('キッチナー'  ,'トロント',    105);
insert into travel values('キッチナー'  ,'バリー',      155);
insert into travel values('ノースベイ'  ,'ペンブローク',220);
insert into travel values('ペンブローク','オタワ',      150);
insert into travel values('バリー'      ,'トロント',     90);
insert into travel values('トロント'    ,'ベルビル',    190);
insert into travel values('ベルビル'    ,'オタワ',      230);
insert into travel values('ベルビル'    ,'ペンブローク',230);
insert into travel values('バリー'      ,'ハンツビル',  125);
insert into travel values('ハンツビル'  ,'ノースベイ',  130);
insert into travel values('ハンツビル'  ,'ペンブローク',245);

insert into travel
select destination, origin, distance
from travel;
commit;


SQL

col path for a65

with rec(origin,destination,distance,path) as(
select origin,destination,0,cast(origin as varchar2(200))
  from travel
 where origin = 'キッチナー'
union all
select b.origin,b.destination,a.distance+b.distance,
a.path || ',' || b.origin
  from rec a,travel b
 where a.origin != 'ペンブローク'
   and b.destination = a.origin)
CYCLE origin SET IsLOOP TO 'Y' DEFAULT 'N'
select distinct distance,path
  from rec
 where origin = 'ペンブローク'
order by distance;


解説

Cycle句で再訪を防いでます。

OracleSQLパズル 10-139 最短距離問題