Oracle - 在图中计算路由值

时间:2016-06-20 20:27:11

标签: sql oracle graph connect-by

我正在使用Oracle 10。

我有描述图表节点和路径的数据。 我想建立一个查询来描述端点之间的所有路由及其价值或遍历成本。

示例数据:

NodeId1    NodeId2    Endpoint1    Endpoint2    Value
   1170       8406        34210       (null)       39
   8411       8410       (null)        34260        1
   8411       4275       (null)        32231       60
   8406       8405       (null)        34287        1
   8406       8411       (null)       (null)       26

这描述了一个如下图所示(成本在括号中,端点是方括号):

1170              8406             8405
 []-----------------o----------------[]
         (39)       |        (1)
                    |
                    |(27)
                    |              4275
               8411 o----------------[]
                    |      (60)
                    |
                 (1)|
                    |
                    []
                  8410

输出应如下所示:

Start     End    Cost
 1170    4275     126
 1170    8405      40
 1170    8410      67
 8405    4275      88
 8405    8410      29
 4275    8410      61

我真的不需要输出两种方式(1170到8406和8406到1170),但它可以帮助进一步使用结果,所以如果它可以包含,它会很好。

1 个答案:

答案 0 :(得分:0)

Oracle安装程序

CREATE FUNCTION sum_Number_List(
  i_str    IN  VARCHAR2,
  i_delim  IN  VARCHAR2 DEFAULT ','
) RETURN NUMBER DETERMINISTIC
AS
  p_result       NUMBER := 0;
  p_start        NUMBER(5) := 1;
  p_end          NUMBER(5);
  c_len CONSTANT NUMBER(5) := LENGTH( i_str );
  c_ld  CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
  IF c_len > 0 THEN
    p_end := INSTR( i_str, i_delim, p_start );
    WHILE p_end > 0 LOOP
      p_result := p_result + TO_NUMBER( SUBSTR( i_str, p_start, p_end - p_start ) );
      p_start := p_end + c_ld;
      p_end := INSTR( i_str, i_delim, p_start );
    END LOOP;
    IF p_start <= c_len + 1 THEN
      p_result := p_result + TO_NUMBER( SUBSTR( i_str, p_start, c_len - p_start + 1 ) );
    END IF;
  END IF;
  RETURN p_result;
END;
/

CREATE TABLE table_name ( NodeId1, NodeId2, Endpoint1, Endpoint2, Value ) AS
SELECT 1170, 8406, 34210, null,  39 FROM DUAL UNION ALL
SELECT 8411, 8410, null,  34260,  1 FROM DUAL UNION ALL
SELECT 8411, 4275, null,  32231, 60 FROM DUAL UNION ALL
SELECT 8406, 8405, null,  34287,  1 FROM DUAL UNION ALL
SELECT 8406, 8411, null,  null,  26 FROM DUAL;

<强>查询

WITH directedgraph AS (
  SELECT NodeID1 AS f,
         NodeID2 AS t,
         EndPoint1 AS isStart,
         EndPoint2 AS isEnd,
         Value
  FROM   table_Name
  UNION ALL
  SELECT NodeID2 AS f,
         NodeID1 AS t,
         EndPoint2 AS isStart,
         EndPoint1 AS isEnd,
         Value
  FROM   table_Name
)
SELECT CONNECT_BY_ROOT( f ) AS "START",
       t AS "END",
       SUM_NUMBER_LIST( SUBSTR( SYS_CONNECT_BY_PATH( value, ',' ), 2 ) ) AS cost
FROM   directedgraph
WHERE  CONNECT_BY_ISLEAF = 1
AND    isEnd IS NOT NULL
START WITH isStart IS NOT NULL
CONNECT BY NOCYCLE
           PRIOR t = f
AND        PRIOR f <> t;

<强>输出

     START        END       COST
---------- ---------- ----------
      1170       8405         40 
      1170       4275        125 
      1170       8410         66 
      4275       1170        125 
      4275       8405         87 
      4275       8410         61 
      8405       1170         40 
      8405       4275         87 
      8405       8410         28 
      8410       4275         61 
      8410       1170         66 
      8410       8405         28