3

这是此查询的完整示例数据集,没有修剪任何节点与搜索字符串匹配的树:

级别父 ID 文本
---------------------------------------------
0 0 1 顶层
1 1 2 富
1 1 3 其他
1 1 4 英尺
0 0 7 顶层2
1 7 8 秒级
1 7 9 另一个二级

如果用户搜索“foo”,我需要返回以下内容:

0 0 1 顶层
1 1 2 富
1 1 4 英尺

实际情况稍微复杂一些(即我想要返回的树中的三个级别),但这抓住了问题。在英语中,返回与搜索字符串匹配的节点的祖先树,该搜索字符串从文本列上的匹配节点开始,并返回所有祖先。

我是 Oracle 的新手(至少最近是这样)并尝试添加到 CONNECT BY 子句但没有任何成功 - 总是返回以下内容:

1 1 2 富
1 1 4 英尺

PS - 关于此的 oracle 文档和示例暗示 CONNECT_BY_ROOT 将捕获祖先,但它似乎所做的只是返回顶级(ROOT)值。

4

3 回答 3

3

要从下往上遍历,重要的是CONNECT BY PRIOR)之后的值的顺序,order by用于反转输出(因为根是 foo)并distinct删除重复的顶层值:

SELECT DISTINCT LEVEL, id, text
FROM t1
CONNECT BY PRIOR parent = id
START WITH text = 'foo'
ORDER BY LEVEL DESC

注意:如果您将孩子添加到 foo 并切换 CONNCT BY PRIOR id = parent 您将获得孩子

如果您想查看整个层次结构,您可以找到树的顶部(通过查找没有父级的行)

SELECT id
FROM t1
WHERE parent=0
CONNECT BY PRIOR parent = id
START WITH text = 'foo'

然后将其用作 START WITH id(并反转外部查询中树遍历的顺序,id = parent):

SELECT DISTINCT LEVEL, id, text
FROM t1
CONNECT BY PRIOR id = parent
START WITH id IN 
(
    SELECT id
    FROM t1
    WHERE parent=0
    CONNECT BY PRIOR parent = id
    START WITH text = 'foo'
)
ORDER BY LEVEL DESC
于 2011-10-13T14:25:17.677 回答
0

Depending upon your use of the LEVEL column (as per my comment).

Info on Oracle Hierarchical Queries: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/queries003.htm

This returns what you ask for if LEVEL is the Oracle pseudocolumn:

WITH t AS (SELECT 0 AS parent,
                  1 AS id,
                  'toplevel' AS text FROM DUAL
           UNION
           SELECT 1 AS parent,
                  2 AS id,
                  'foo' AS text FROM DUAL
           UNION
           SELECT 1 AS parent,
                  3 AS id,
                  'sumthin else' AS text FROM DUAL
           UNION
           SELECT 1 AS parent,
                  4 AS id,
                  'foo' AS text FROM DUAL
           UNION
           SELECT 0 AS parent,
                  7 AS id,
                  'toplevel2' AS text FROM DUAL
           UNION
           SELECT 7 AS parent,
                  8 AS id,
                  'secondlevel' AS text FROM DUAL
           UNION
           SELECT 7 AS parent,
                  9 AS id,
                  'anothersecondlevel' AS text FROM DUAL
          ) 
SELECT UNIQUE
       level,
       parent,
       id,
       text
  FROM t
 START WITH text = 'foo'
 CONNECT BY PRIOR parent = id
 ORDER BY parent;

Returns:

LEVEL PARENT ID TEXT
    2      0  1 toplevel
    1      1  2 foo     
    1      1  4 foo     

If LEVEL is a column in your table then:

WITH t AS (SELECT 0 AS tlevel,
                  0 AS parent,
                  1 AS id,
                  'toplevel' AS text FROM DUAL
           UNION
           SELECT 1 AS tlevel,
                  1 AS parent,
                  2 AS id,
                  'foo' AS text FROM DUAL
           UNION
           SELECT 1 AS tlevel,
                  1 AS parent,
                  3 AS id,
                  'sumthin else' AS text FROM DUAL
           UNION
           SELECT 1 AS tlevel,
                  1 AS parent,
                  4 AS id,
                  'foo' AS text FROM DUAL
           UNION
           SELECT 0 AS tlevel,
                  0 AS parent,
                  7 AS id,
                  'toplevel2' AS text FROM DUAL
           UNION
           SELECT 1 AS tlevel,
                  7 AS parent,
                  8 AS id,
                  'secondlevel' AS text FROM DUAL
           UNION
           SELECT 1 AS tlevel,
                  7 AS parent,
                  9 AS id,
                  'anothersecondlevel' AS text FROM DUAL
          ) 
SELECT UNIQUE
       tlevel,
       parent,
       id,
       text
  FROM t
 START WITH text = 'foo'
 CONNECT BY PRIOR parent = id
 ORDER BY parent;

Returns:

TLEVEL PARENT ID TEXT
     0      0  1 toplevel
     1      1  2 foo     
     1      1  4 foo     

Hope it helps...

于 2011-10-13T14:11:25.120 回答
0

我对“仅返回完整树的 Oracle 分层查询”部分的看法是:

SELECT Parent_ID    
     , Child_ID 
     , INITIAL_Parent_ID
     , child_level
     , INITIAL_Parent_ID || children_CHAIN AS CONNECTION_CHAIN
FROM ( SELECT CONNECT_BY_ROOT Parent_ID AS INITIAL_Parent_ID
            , Parent_ID
            , Child_ID
            , LEVEL AS child_level
            , SYS_CONNECT_BY_PATH(Child_ID, '/') AS children_chain
       FROM REF_DECOMMISSIONS
       CONNECT BY NOCYCLE Parent_ID = PRIOR Child_ID
     )
WHERE INITIAL_Parent_ID NOT IN (SELECT Child_ID FROM REF_DECOMMISSIONS)
;

要将树过滤为包含特定子项的树,您需要在最后一个 WHERE 中添加另一个条件以进一步过滤 INITIAL_Parent_ID。查询将变为:

WITH ROOT_TREES AS
( SELECT Parent_ID  
       , Child_ID   
       , INITIAL_Parent_ID
       , child_level
       , INITIAL_Parent_ID || children_CHAIN AS CONNECTION_CHAIN
  FROM ( SELECT CONNECT_BY_ROOT Parent_ID AS INITIAL_Parent_ID
              , Parent_ID
              , Child_ID
              , LEVEL AS child_level
              , SYS_CONNECT_BY_PATH(Child_ID, '/') AS children_chain
         FROM REF_DECOMMISSIONS
         CONNECT BY NOCYCLE Parent_ID = PRIOR Child_ID
       )
  WHERE INITIAL_Parent_ID NOT IN (SELECT Child_ID FROM REF_DECOMMISSIONS)
)
SELECT * 
  FROM root_trees 
WHERE INITIAL_Parent_ID IN (SELECT INITIAL_Parent_ID 
                              FROM root_trees 
                             WHERE Child_ID = 123)
;
于 2016-01-26T14:15:48.013 回答