Oracle数据库顺序树的兄弟姐妹表



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

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的siblingNode为NULL, E的F的ID为siblingNode, D的E的ID为siblingNode。

到目前为止,我已经完成了一个常见的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的新手,不知道是否有更好的方法来做上面的任何事情。我欢迎任何评论,特别想知道如何通过他们的链接来订购兄弟姐妹。

样本数据:

ID: 1;dataID => ' - ';parentNode:空;siblingNode:空;
ID: 2;dataID => ' 1 ';parentNode: 1;siblingNode: 3;
ID: 3;dataID => ' 6 ';parentNode: 1;siblingNode:空;
ID: 4;dataID =>‘*’;parentNode:空;siblingNode:空;
ID: 5;dataID => ' 8 ';parentNode: 4;siblingNode:空;
ID: 6;dataID => ' 8 ';parentNode: 4;siblingNode: 5;

所需输出:

ID: 1;润色:'+ 6 1'
ID: 4;抛光:'* 8 8'

ORDER SIBLINGS BY ID ASC的问题是第一个输出将返回'- 16 ',这与'- 61 1'不同。

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

如果我正确理解你的问题,你想要一个分层查询返回波兰符号(叶节点)与其相应的节点->根节点路径。然后,您将使用该查询来提供波兰语符号关系的视图。

可以使用SYS_CONNECT_BY_PATH代替LISTAGG函数,并使用空格或任何其他有效的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;

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

我已经成功地生成了一个查询,通过连接到由siblingNode连接的第二个查询并按兄弟级别排序,该查询为我提供了预期的结果:

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

最新更新