【问题标题】:Summarize in ORACLE hierarchical queryORACLE分层查询中的总结
【发布时间】:2013-12-21 08:20:41
【问题描述】:

我需要一些建议,因为我对分层查询很陌生 :( IE。我有下表:

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;

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

比你!

【问题讨论】:

  • 你用的是什么版本?如果是 11gR2 或更高版本,递归子查询分解可能比 CONNECT BY 工作得更好。

标签: sql oracle hierarchical connect-by


【解决方案1】:

使用递归 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     

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2015-10-15
      相关资源
      最近更新 更多