在ORACLE层次查询中总结

时间:2013-12-04 17:45:28

标签: sql oracle hierarchical connect-by

我需要一些建议,因为我对分层查询很新:( 即我有下表:

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)
.               .               .
.               .               .
.               .               .

我已经想到了,应该使用CONNECT BY PRIOR语句并编写一个贯穿层次结构的查询:

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

我真的可以使用一些帮助来获得价格。

比你!

2 个答案:

答案 0 :(得分:2)

使用递归sql更简单明了(从/更改为f / t以避免使用关键字)

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 :(得分:1)

这不是最终解决方案,但可能是一个起点。它将价格显示为文本而非nubmer,我不知道快速解决方案来总结它们。

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;

我只从旧金山选择了journes以获得更好的概述。

结果:

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