2013-12-04 3 views
1

мне нужно некоторые советуют, потому что я новичок в иерархических запросов :( Т.е. я в следующей таблице:Обобщить в ORACLE иерархического запроса

CREATE TABLE routes 
(
    from  VARCHAR2(15), 
    to   VARCHAR2(15), 
    price  NUMBER 
); 

INSERT INTO routes VALUES('San Francisco', 'Denver', 1000); 
INSERT INTO routes VALUES('San Francisco', 'Dallas', 10000); 
INSERT INTO routes VALUES('Denver', 'Dallas', 500); 
INSERT INTO routes VALUES('Denver', 'Chicago', 2000); 
INSERT INTO routes VALUES('Dallas', 'Chicago', 600); 
INSERT INTO routes VALUES('Dallas', 'New York', 2000); 
INSERT INTO routes VALUES('Chicago', 'New York', 3000); 
INSERT INTO routes VALUES('Chicago', 'Denver', 2000); 

Я хочу, чтобы рассчитать цену по иерархии, чтобы получить следующий результат:

FROM   TO    PRICE 
--------------- --------------- ----- 
San Francisco Dallas   10000 //San Francisco -> Dallas 
San Francisco Denver   1000 //San Francisco -> Denver 
San Francisco Chicago   10600 //San Francisco --> Dallas --> Chicago (10000 + 600) 
San Francisco New York  12000 //San Francisco --> Dallas --> New York (10000 + 200) 
San Francisco Chicago   3000 //San Francisco --> Denver --> Chicago (1000 + 2000) 
San Francisco Dallas   1500 //San Francisco --> Denver --> Dallas (1000 + 500) 
.    .    . 
.    .    . 
.    .    . 

Я alreary себе, что ПРИОР оператор CONNECT BY следует использовать и написал запрос, который проходит через иерархию:

SELECT 
    CONNECT_BY_ROOT from, 
    to 
    FROM routes 
    CONNECT BY NOCYCLE PRIOR to = from; 

Я действительно мог бы использовать некоторую помощь, как получить цены.

Чем вы!

+0

Какую версию вы используете? Если 11gR2 или выше, рекурсивный факторинг подзапроса может работать лучше, чем CONNECT BY. –

ответ

2

гораздо проще с помощью рекурсивного SQL (изменяется от/до до е/т, чтобы избежать использования ключевых слов)

CREATE TABLE routes 
(
    f  VARCHAR2(15), 
    t   VARCHAR2(15), 
    price  NUMBER 
); 

INSERT INTO routes VALUES('San Francisco', 'Denver', 1000); 
INSERT INTO routes VALUES('San Francisco', 'Dallas', 10000); 
INSERT INTO routes VALUES('Denver', 'Dallas', 500); 
INSERT INTO routes VALUES('Denver', 'Chicago', 2000); 
INSERT INTO routes VALUES('Dallas', 'Chicago', 600); 
INSERT INTO routes VALUES('Dallas', 'New York', 2000); 
INSERT INTO routes VALUES('Chicago', 'New York', 3000); 
INSERT INTO routes VALUES('Chicago', 'Denver', 2000); 


with 
t1 (start_loc, current_loc, route, total_price, stops) as 
    (select distinct f,f, cast(f as varchar2(4000)), 0, 0 
    from routes 
    union all 
    select start_loc, t, route||'->'||t, total_price+price , stops+1 
    from routes r 
      join t1 on (f = current_loc and instr(route,t)=0) 
) 
select * 
from t1 
where stops <> 0 
order by  
     start_loc, current_loc, total_price ASC 

РЕЗУЛЬТАТЫ:

START_LOC  CURRENT_LOC ROUTE            TOTAL_PRICE STOPS 
-------------- ------------ ------------------------------------------------- ------------ ------ 
Chicago  Dallas  Chicago->Denver->Dallas       2500   2  
Chicago  Denver  Chicago->Denver         2000   1  
Chicago  New York  Chicago->Denver->Dallas->New York     4500   3  
Chicago  New York  Chicago->New York         3000   1  
Dallas   Chicago  Dallas->Chicago         600   1  
Dallas   Denver  Dallas->Chicago->Denver       2600   2  
Dallas   New York  Dallas->Chicago->New York       3600   2  
Dallas   New York  Dallas->New York         2000   1  
Denver   Chicago  Denver->Chicago         2000   1  
Denver   Chicago  Denver->Dallas->Chicago       1100   2  
Denver   Dallas  Denver->Dallas         500   1  
Denver   New York  Denver->Chicago->New York       5000   2  
Denver   New York  Denver->Dallas->Chicago->New York     4100   3  
Denver   New York  Denver->Dallas->New York       2500   2  
San Francisco Chicago  San Francisco->Dallas->Chicago     10600  2  
San Francisco Chicago  San Francisco->Denver->Chicago     3000   2  
San Francisco Chicago  San Francisco->Denver->Dallas->Chicago   2100   3  
San Francisco Dallas  San Francisco->Dallas        10000  1  
San Francisco Dallas  San Francisco->Denver->Dallas      1500   2  
San Francisco Denver  San Francisco->Dallas->Chicago->Denver   12600  3  
San Francisco Denver  San Francisco->Denver        1000   1  
San Francisco New York  San Francisco->Dallas->Chicago->New York   13600  3  
San Francisco New York  San Francisco->Dallas->New York     12000  2  
San Francisco New York  San Francisco->Denver->Chicago->New York   6000   3  
San Francisco New York  San Francisco->Denver->Dallas->Chicago->New York 5100   4  
San Francisco New York  San Francisco->Denver->Dallas->New York   3500   3  
1

Это не окончательное решение, но, может быть, начиная точка. Он показывает цену как текст не как нубмер, я не знаю быстрого решения, чтобы подвести итог.

SELECT 
    SUBSTR(SYS_CONNECT_BY_PATH(FROM||'->'||TO, '.'), 2) AS journey, 
    SUBSTR(SYS_CONNECT_BY_PATH(price, '+'), 2) AS prices 
FROM routes 
START WITH FROM_airport = 'San Francisco' 
CONNECT BY NOCYCLE PRIOR TO = FROM; 

Я выбрал только журналы из Сан-Франциско, чтобы получить лучший обзор.

Результат:

JOURNEY                |PRICES 
San Francisco->Dallas             |10000 
San Francisco->Dallas.Dallas->Chicago         |10000+600 
San Francisco->Dallas.Dallas->Chicago.Chicago->Denver     |10000+600+2000 
San Francisco->Dallas.Dallas->Chicago.Chicago->New York    |10000+600+3000 
San Francisco->Dallas.Dallas->New York         |10000+2000 
San Francisco->Denver             |1000 
San Francisco->Denver.Denver->Chicago         |1000+2000 
San Francisco->Denver.Denver->Chicago.Chicago->New York    |1000+2000+3000 
San Francisco->Denver.Denver->Dallas         |1000+500 
San Francisco->Denver.Denver->Dallas.Dallas->Chicago     |1000+500+600 
San Francisco->Denver.Denver->Dallas.Dallas->Chicago.Chicago->New York |1000+500+600+3000 
San Francisco->Denver.Denver->Dallas.Dallas->New York     |1000+500+2000 
Смежные вопросы