【问题标题】:Oracle sql hierarchical or recursive query on table data with graph nodes使用图形节点对表数据进行 Oracle sql 分层或递归查询
【发布时间】:2018-03-28 09:48:47
【问题描述】:

这是我的表“graphtable”,其中包含图形节点。每个元组代表一条无向边。

╔═════════╦═════════╗
║ NODEONE ║ NODETWO ║
╠═════════╬═════════╣
║ A       ║ A       ║
║ A       ║ A       ║
║ A       ║ B       ║
║ A       ║ B       ║
║ A       ║ A       ║
║ C       ║ D       ║
║ C       ║ A       ║
║ D       ║ E       ║
║ A       ║ E       ║
║ D       ║ A       ║
║ G       ║ K       ║
║ G       ║ G       ║
║ K       ║ K       ║
║ K       ║ L       ║
║ L       ║ M       ║
║ Y       ║ M       ║
║ G       ║ L       ║
║ G       ║ L       ║
║ X       ║ Z       ║
║ D       ║ D       ║
║ I       ║ I       ║
╚═════════╩═════════╝

如您所见,此表中有四个不同的无向图。

  1. 节点(A、B、C、D、E)
  2. 节点(L、K、G、M、Y)
  3. 节点(一)
  4. 节点(X,Z)

我尝试了类似于下面发布的查询;

select nodeone,nodetwo
from
graphtable
start with NODEONE='D'
connect by nocycle prior nodeone=nodetwo

我也可以使用递归查询来遍历图形。

但是,如果我从特定图形中的任何节点开始,我需要获取特定图形中涉及的所有元组。但是,我没有从我的任何查询中得到该结果。

从 nodeone='A' 开始;似乎返回了所有边缘,但边缘“D-D”不存在。从 nodeone='D' 开始;似乎没有返回任何接近以前的结果。

请帮忙.. 我提前感谢任何帮助。 谢谢。

【问题讨论】:

  • 这可能没有帮助,但在关系数据库中实现图形并不理想。特别是当有针对它们优化的 DBMS 时,例如新4J。如果您对图表感兴趣,那么我建议您看看。
  • 谢谢。明白你的意思。当然我会看看 Neo4j。

标签: sql oracle graph-theory hierarchical-query


【解决方案1】:

每个元组代表一条无向边。

您没有将其视为无向边 - 您将其视为有向边,因为您只检查 prior nodeone=nodetwo 并且不检查当前边的任一端是否可以与前一条边的任一端匹配。

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE graphtable ( NODEONE, NODETWO ) AS
  SELECT 'A', 'A' FROM DUAL UNION ALL
  SELECT 'A', 'A' FROM DUAL UNION ALL
  SELECT 'A', 'B' FROM DUAL UNION ALL
  SELECT 'A', 'B' FROM DUAL UNION ALL
  SELECT 'A', 'A' FROM DUAL UNION ALL
  SELECT 'C', 'D' FROM DUAL UNION ALL
  SELECT 'C', 'A' FROM DUAL UNION ALL
  SELECT 'D', 'E' FROM DUAL UNION ALL
  SELECT 'A', 'E' FROM DUAL UNION ALL
  SELECT 'D', 'A' FROM DUAL UNION ALL
  SELECT 'G', 'K' FROM DUAL UNION ALL
  SELECT 'G', 'G' FROM DUAL UNION ALL
  SELECT 'K', 'K' FROM DUAL UNION ALL
  SELECT 'K', 'L' FROM DUAL UNION ALL
  SELECT 'L', 'M' FROM DUAL UNION ALL
  SELECT 'Y', 'M' FROM DUAL UNION ALL
  SELECT 'G', 'L' FROM DUAL UNION ALL
  SELECT 'G', 'L' FROM DUAL UNION ALL
  SELECT 'X', 'Z' FROM DUAL UNION ALL
  SELECT 'D', 'D' FROM DUAL UNION ALL
  SELECT 'I', 'I' FROM DUAL;

查询 1

SELECT DISTINCT
       nodeone,
       nodetwo,
       rowid    -- Included as a unique id to differentiate edges with the
                -- same start/end points.
FROM   graphtable
START WITH NODEONE = 'D'
CONNECT BY NOCYCLE
   PRIOR nodeone IN ( nodeone, nodetwo )
OR PRIOR nodetwo IN ( nodeone, nodetwo )
ORDER SIBLINGS BY nodeone, nodetwo

Results

| NODEONE | NODETWO |                     ROWID |
|---------|---------|---------------------------|
|       A |       A | oracle.sql.ROWID@57528909 |
|       A |       A | oracle.sql.ROWID@3d7f5c9c |
|       A |       A | oracle.sql.ROWID@777a44ea |
|       A |       B | oracle.sql.ROWID@1ca773d6 |
|       A |       B | oracle.sql.ROWID@5f7ebb8a |
|       A |       E | oracle.sql.ROWID@18229745 |
|       C |       A | oracle.sql.ROWID@3d5acdbf |
|       C |       D | oracle.sql.ROWID@1ac42001 |
|       D |       A | oracle.sql.ROWID@30cc6a38 |
|       D |       D | oracle.sql.ROWID@3cd85bdb |
|       D |       E | oracle.sql.ROWID@57845eca |

【讨论】:

  • 感谢您的回复。该逻辑适用于所有用例,例如 START WITH NODEONE = 'E' 或 nodetwo='E'。但是对于非常大的实际表,查询需要永远结束。我需要找到一种方法来加速它。非常感谢!!
猜你喜欢
  • 1970-01-01
  • 2019-08-18
  • 2014-10-27
  • 1970-01-01
  • 2023-03-07
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多