Sql 如何在connect by中获取具有给定ID的完整子分支

Sql 如何在connect by中获取具有给定ID的完整子分支,sql,oracle,connect-by,Sql,Oracle,Connect By,我想从parent_id=null到具有给定子id的childs获取分支 select * from company s start with s.parent_id is null and s.id = 56 connect by prior s.id = s.parent_id 结果是元素id为56的完整分支 如何选择具有选定子对象的分支 例如: 现在的结果是: id parent_id 56 null 57 56 58 57 59 57 60

我想从parent_id=null到具有给定子id的childs获取分支

select *
from company s
start with s.parent_id is null and s.id = 56
connect by prior s.id = s.parent_id
结果是元素id为56的完整分支

如何选择具有选定子对象的分支

例如:

现在的结果是:

id   parent_id
56     null
57      56
58      57
59      57
60      56
61      60 
我想要实现的是,在给定子id为57的情况下,仅选择该分支

id   parent_id
56     null
57      56
58      57
59      57

without not given child id:
60      56
61      60 

一些简单的查询,应该满足您的要求:

编辑:在查询中添加注释

EDIT2:最小化了SYS_CONNECT_BY_路径的使用,因此更难达到其大小限制

    WITH param AS -- this is just our parameter to be used in further subqueries (ID and regex pattern for regexp_like expression)
(
  SELECT
    57 AS id
    ,'(\s?)('||57||')(\s|\W)' AS regex
  FROM
    dual
)
, parent AS -- here we get the inverted hierarchy - searching for the root node of the branch where ID given as parameter exists
(
SELECT
  s.*
FROM
  company s
  ,param
CONNECT BY PRIOR s.parent_id = s.id
START WITH s.id = param.id
)
, children AS -- here we get all the children of the root node we found in parent subquery
(
SELECT
  s.*
  ,CASE
    WHEN LEVEL >= MAX(CASE WHEN s.id = param.id THEN LEVEL ELSE NULL END) OVER (PARTITION BY NULL) THEN 
      SYS_CONNECT_BY_PATH(s.id,' ') 
    ELSE NULL
  END AS path -- this gives us the hierarchical path
  ,LEVEL AS lvl -- this gives us children's levels
  ,MAX(CASE WHEN s.id = param.id THEN LEVEL ELSE NULL END) OVER (PARTITION BY NULL) AS id_level -- this gives the level of the children given as a parameter
FROM
  company s
  ,param
CONNECT BY PRIOR s.id = s.parent_id
START WITH s.id = (SELECT parent.id FROM parent WHERE parent.parent_id IS NULL)
)
-- now we select from the all children hierarchy our desired branch
SELECT
  c.*
FROM
  children c
  ,param
WHERE
  1 = CASE WHEN lvl > c.id_level AND REGEXP_LIKE(c.path, param.regex) THEN 1 -- if current id is of higher level (is a child of our paremeter ID), it must have our parameter ID in it's path
           WHEN lvl = c.id_level AND c.id = param.id THEN 1 -- if the level is equal to our parameter's ID's leve, it has to be our paremeter
           WHEN lvl < c.id_level AND EXISTS(SELECT 1 FROM parent WHERE parent.id = c.id) THEN 1 -- if current level is lower (may be a parent of our parmeter ID) it has to exists in the reverse hierarchy (thus, must be a parent or grandparent etc. of our paremter node)
           ELSE 0
      END

顺便说一句,在阅读了Carlo Sirna的解决方案后,我发现他的解决方案更好:

这个解决方案适用于任何可能的树深度,并且不使用正则表达式或字符串连接。应该很容易理解:

    with
       all_children_of_57 as 
       (     
          -- all nodes that can be reached by starting a recursive descent from node 57 
          select id
          from company s
          start with s.id = 57
          connect by prior s.id = s.parent_id 
       ),
       all_ancestors_of_57 as
       (
          -- all ANCESTORS that can be reached by walking up the tree (FROM CHILD TO PARENT), 
          -- starting from node 57 (this is a linear recursion)
          select id
          from company s
          start with s.id = 57  
          connect by  s.id = prior s.parent_id  
       ),
       nodes_in_branch as
       (  
          -- we are interested only in nodes extracted from the above two queries
          select * 
          from company
          where id in (select id from all_children_of_57)
             or id in (select id from all_ancestors_of_57)
       )

    -- we do the recursion on the result of nodes_in_branch  
    select *
    from nodes_in_branch s
    start with s.parent_id is null 
    connect by prior s.id = s.parent_id

您能否尝试解释此碎片中发生的情况此解决方案使用SYS_CONNECT_BY_path.id“”限制树的深度,因为SYS_CONNECT_BY生成包含所有遍历节点的字符串,并且此字符串的长度限制为varchar2字段的最大长度,所以它并不适用于所有可能的情况,至少如果我正确理解它的内部工作原理的话,它是非常完整的。我的另一个问题是,我如何选择根元素,而不是将每个元素的路径命名为给定id的My,然后选择他的childs。我想跳过根和给定之间的元素,但我想在根>11>25>选择之间有一个路径,这将导致3个元素:第一个=根,第二个=名称=11>25,第三个=选择