На информационной панели представлено несколько прямых маршрутов. У каждого своя стоимость. Есть маршруты, по которым доехать на автобусе с пересадками выгоднее, чем прямой рейс. Задача для программиста: написать SQL-запрос, который выводит все возможные маршруты начиная с города указанного, как место отправления. Для каждого маршрута необходимо подсчитать стоимость. Если есть несколько маршрутов до одного пункта назначения, вывести самый дешёвый из них. Обратные маршруты не выводить.
Автобусные маршруты представлены в виде таблицы:
ID | ORIGIN | DESTINATION | COST |
1 | MSO | SPB | 500 |
2 | MSO | KRD | 200 |
3 | MSO | SRG | 400 |
4 | KRD | SRG | 100 |
5 | KRD | RVD | 200 |
6 | RVD | VVK | 1000 |
7 | VVK | OCN | 50 |
with function getpathsum(sumpath varchar2) return number is v_res number;
begin
with liststr as
(select regexp_substr(sumpath, '[^/]+', 1, level) c1
from dual
connect by level <= regexp_count(sumpath, '/'))
select sum(cost)
into v_res
from liststr
,busroutes
where origin || '-' || destination = c1;
return v_res;
end;
busroutes_cost as(
select cbr
,path
,cost
,getpathsum(path) as routecost
from (select connect_by_root(f.origin) || '-' || f.destination as cbr
,sys_connect_by_path(f.origin || '-' || f.destination, '/') as path
,f.cost
from busroutes f
connect by prior f.destination = f.origin)),
busroutes_cost_sort as (
select cbr
,path
,routecost
,row_number() over(partition by cbr order by routecost) as rn
from busroutes_cost)
select cbr
,path
,routecost
from busroutes_cost_sort
where rn = 1
select connect_by_root(f.origin) || '-' || f.destination as cbr
,sys_connect_by_path(f.origin || '-' || f.destination, '/') as path
,f.cost
from busroutes f
connect by prior f.destination = f.origin
with function getpathsum(sumpath varchar2) return number is v_res number;
begin
with liststr as
(select regexp_substr(sumpath, '[^/]+', 1, level) c1
from dual
connect by level <= regexp_count(sumpath, '/'))
select sum(cost)
into v_res
from liststr
,busroutes
where origin || '-' || destination = c1;
return v_res;
end;
Функция проставляет порядковый номер в пределах уникального маршрута, предварительно отсортировав их по стоимости: 1 - самому дешёвому маршруту. Далее, выбираются маршруты, у которых rn = 1
,row_number() over(partition by cbr order by routecost) as rn