【问题标题】:Oracle DB Order Tree Siblings By Sibling Linked ListOracle DB Order Tree Siblings by Sibling Linked List
【发布时间】:2014-03-15 00:06:12
【问题描述】:

我打算将树对象存储在数据库表中。这是我的架构:

CREATE TABLE Nodes (
  ID number(11) NOT NULL,
  dataID number(11) NOT NULL,
  parentNode number(11),
  siblingNode number(11),
);

假设我有三棵树 A、B、C,其根节点的父节点为 NULL。我想从节点表中选择所有记录,这些记录按它们所属的树分组,排序类似于深度优先搜索,兄弟姐妹按各自的链表排序。例如,如果 D、E 和 F 是节点 A 的子节点,并且预期的顺序是 F->E->D,则 F 的兄弟节点为 NULL,E 的 F 的 ID 为兄弟节点,D 的 E 的 ID 为兄弟节点.

到目前为止,我已经完成了一个普通的 CONNECT BY 查询,并且我看到有一个 ORDER SIBLINGS BY 子句,但这只能通过对升序或降序值进行排序,而不是链表。到目前为止,我的查询只是按 ID 排序,没有考虑兄弟链接(如果可以保证兄弟的输入顺序,则可以工作)。

SELECT ID, connect_by_root(ID) root
FROM Nodes
START WITH parentNode IS NULL
CONNECT BY PRIOR ID = parentNode
ORDER SIBLINGS BY ID ASC;

最终我想使用 LISTAGG 从数据函数中创建一个字符串,以在我的树上创建一个视图。此视图将每棵树 (A,B,C) 包含一行,其中包含以波兰表示法表示树的字符串。到目前为止,我有:

SELECT DISTINCT connect_by_root(ID) root, LISTAGG(dataString(ID), ' ') WITHIN GROUP (ORDER BY ID ASC) OVER (PARTITION BY connect_by_root(ID)) polish
FROM Nodes
START WITH parentNode IS NULL
CONNECT BY PRIOR ID = parentNode
ORDER SIBLINGS BY ID ASC;

我是 Oracle DB 的新手,不知道是否有更好的方法来执行上述任何操作。我欢迎任何 cmets,特别想知道如何通过链接对兄弟姐妹进行排序。

样本数据:

ID:1;数据ID=>'-';父节点:空;兄弟节点:空;
编号:2;数据ID=>'1';父节点:1;兄弟节点:3;
编号:3;数据ID=>'6';父节点:1;兄弟节点:空;
编号:4;数据ID=>'*';父节点:空;兄弟节点:空;
编号:5;数据ID=>'8';父节点:4;兄弟节点:空;
编号:6;数据ID=>'8';父节点:4;兄弟节点:5;

期望的输出:

ID:1;波兰语:'+ 6 1'
编号:4;波兰语:'* 8 8'

ORDER SIBLINGS BY ID ASC 的问题是第一个输出将返回与“- 6 1”不同的“- 1 6”。

我已经创建了一个演示问题的示例数据。此外,由于某种原因,它不会让我使用 ORDER SIBLINGS BY 子句...... http://sqlfiddle.com/#!4/6ec46/4

【问题讨论】:

  • 你考虑过level伪列和按level_alias排序的父查询吗?
  • 请发布一些示例数据和所需的输出。

标签: sql oracle tree hierarchy


【解决方案1】:

如果我正确理解您的问题,您希望 Hierarchical Query 返回波兰表示法(叶节点)及其对应的节点 -> 根节点路径。然后,您将使用此查询来提供波兰表示法关系的视图。

除了LISTAGG 函数,您可以使用SYS_CONNECT_BY_PATH 并使用空格或任何其他有效的VARCHAR 作为分隔符吗?查询将如下所示:

SELECT DISTINCT ID AS root, SYS_CONNECT_BY_PATH(dataString(ID), ' ') POLISH
FROM Nodes
START WITH parentNode IS NULL
CONNECT BY PRIOR ID = parentNode
ORDER SIBLINGS BY ID ASC;

如果我误解了你的问题,请告诉我,我会更新我的答案。

【讨论】:

  • 简单地将 CONNECT BY 子句更改为 CONNECT BY ID = PRIOR parentNode 有帮助吗?
  • 感谢您的回复!但是,SYS_CONNECT_BY_PATH 并不构成解析树的波兰符号。在我的示例数据中,我会得到六个字符串:'-'、'- 6'、'- 1'、''、' 8'、'* 8',没有一个是预期的“- 6 1”和“* 8 8”结果。
【解决方案2】:

我已经成功地生成了一个查询,它通过加入由兄弟节点连接的第二个查询并按兄弟级别排序来给我预期的结果:

SELECT DISTINCT wut.root,
   LISTAGG(wut.data, ' ')
    WITHIN GROUP (ORDER BY wut.polishOrder)
    OVER (PARTITION BY wut.root) polish
FROM        
( SELECT connect_by_root(n.ID) root, data, ROWNUM polishOrder
 FROM Nodes n
 JOIN
 (SELECT m.ID, LEVEL l
  FROM Nodes m
  START WITH m.siblingNode IS NULL
  CONNECT BY PRIOR m.ID = m.siblingNode) mm
 ON n.ID = mm.ID
     START WITH n.parentNode IS NULL
     CONNECT BY PRIOR n.ID = n.parentNode
     ORDER SIBLINGS BY mm.l
) wut

http://sqlfiddle.com/#!4/94facf/25

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多