Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
给定任何节点作为输入的Oracle SQL完整层次结构_Sql_Oracle_Hierarchical Data - Fatal编程技术网

给定任何节点作为输入的Oracle SQL完整层次结构

给定任何节点作为输入的Oracle SQL完整层次结构,sql,oracle,hierarchical-data,Sql,Oracle,Hierarchical Data,我想在Oracle SQL数据库中创建一个完整的层次搜索查询。 我有一个下表,叫做“项目” 输入是id列中给定id的任意一个。它应该能找到这个身份证的所有孩子,他们的孩子。还有父母和他们的父母。 目前我有以下疑问: select distinct m.id, m.parent_id from item m connect by prior m.id = m.parent_id start with m.parent_id IN ( select m.parent_

我想在Oracle SQL数据库中创建一个完整的层次搜索查询。 我有一个下表,叫做“项目”

输入是id列中给定id的任意一个。它应该能找到这个身份证的所有孩子,他们的孩子。还有父母和他们的父母。 目前我有以下疑问:

select distinct m.id, m.parent_id
    from item m
connect by prior m.id = m.parent_id
    start with m.parent_id IN (
        select m.parent_id
        from item m
        connect by m.id = prior m.parent_id
    start with m.id = 3
    union
    select m.parent_id
        from item m
    where m.parent_id = 3);
目前,它似乎只是为了不选择没有父项(parent_id列为null)的父项而工作。除此之外,它似乎正在发挥作用。如果我的问题可以简化,我也会很感激的

编辑

我想我通过以下查询得到了期望的结果:

select m.id
    from item m
    start with m.id in (
        select m.id
        from item m
        where connect_by_isleaf = 1
        start with m.id = 3
        connect by m.id = prior m.parent_id
    )
    connect by m.parent_id = prior m.id;

现在我有下一个问题。从m.id=3开始。问题是我想从整个查询中创建一个视图。但由于m.id值在不同的查询中发生变化,我无法将其添加为参数。还可以注释掉以m.id=3开头的内容,然后返回所有项之间的所有层次结构。有没有办法创建一些连接?例如:我将查询所有项目的所有这些关系,然后根据某些条件仅获取某些项目关系。

如果要将其用作视图,可以执行以下操作:

WITH rek AS (SELECT item.id
                  , item.name
                  , connect_by_root item.id root_id
               FROM item
              START WITH parent_id IS null
            CONNECT BY NOCYCLE parent_id = PRIOR id)
SELECT startItem.id startId
     , startItem.name startName
     , childItem.id childID
     , childItem.name childName
  FROM rek startItem
  JOIN rek childItem
  USING (root_id)
-- WHERE startItem.id = 3 -- This would be done from outside the view
子查询
rek
将树的所有同级元素与根元素连接起来。然后,您只需使用此查询两次并通过根元素连接它,即可获得通过父子关系连接的所有元素

如果要减少结果集,可以使用
SYS\u CONNECT\u BY\u PATH
来减少结果集:

WITH rek AS (SELECT item.id
                  , item.name
                  , connect_by_root item.id root_id
                  , SYS_CONNECT_BY_PATH(item.id, '/') path
               FROM item
              START WITH parent_id IS null
            CONNECT BY NOCYCLE parent_id = PRIOR id)
SELECT startItem.id startId
     , startItem.name startName
     , childItem.id childID
     , childItem.name childName
     , childItem.path 
  FROM rek startItem
  JOIN rek childItem
    ON startItem.root_id = childItem.root_id
    AND (startItem.path LIKE childItem.path||'/%'
      OR childItem.path LIKE startItem.path||'/%'
      OR childItem.id = startItem.id)

例如,这将只为您的孩子和家长提供起点,而不提供来自其他Leaf的条目。

Oracle设置

CREATE TABLE item ( id, name, parent_id ) AS
  SELECT 1, 'A', NULL FROM DUAL UNION ALL
  SELECT 2, 'B',    1 FROM DUAL UNION ALL
  SELECT 3, 'C',    2 FROM DUAL UNION ALL
  SELECT 4, 'D',    3 FROM DUAL UNION ALL
  SELECT 5, 'E',    2 FROM DUAL;
ID NAME PARENT_ID
-- ---- ---------
1  A    -
2  B    1
3  C    2
4  D    3
5  E    2
您可以使用以下方式获取项目及其所有祖先:

SELECT *
FROM   item
START WITH id = 2
CONNECT BY PRIOR parent_id = id
您可以使用以下方法获取项目的所有子体:

SELECT *
FROM   item
START WITH parent_id = 2
CONNECT BY PRIOR id = parent_id
您可以使用
UNION ALL
将两者结合起来。然而,这将匹配项按增加祖先的顺序排列在祖先之前,然后按减少祖先的顺序排列在后代之后。。。这可能会让人困惑

因此,您可以对查询进行重新排序,以使两者的顺序一致:

SELECT *
FROM   (
  SELECT *
  FROM   item
  START WITH id = 2
  CONNECT BY PRIOR parent_id = id
  ORDER BY LEVEL DESC
)
UNION ALL
SELECT *
FROM   (
  SELECT *
  FROM   item
  START WITH parent_id = 2
  CONNECT BY PRIOR id = parent_id
  ORDER SIBLINGS BY name
);
输出

CREATE TABLE item ( id, name, parent_id ) AS
  SELECT 1, 'A', NULL FROM DUAL UNION ALL
  SELECT 2, 'B',    1 FROM DUAL UNION ALL
  SELECT 3, 'C',    2 FROM DUAL UNION ALL
  SELECT 4, 'D',    3 FROM DUAL UNION ALL
  SELECT 5, 'E',    2 FROM DUAL;
ID NAME PARENT_ID
-- ---- ---------
1  A    -
2  B    1
3  C    2
4  D    3
5  E    2

“如果我的给定查询可以简化”问题是,虽然查询项的后代很简单,查询项的祖先也很简单,但在同一个查询中同时执行这两个操作是很棘手的。预期的输出格式是什么?预期的输出是所有父项和所有子项。从我的示例数据来看,所有这些节点都是通过父节点和子节点连接的,直到没有父节点的根节点。因此,所有这些都应该被选中。您的查询是错误的,因为当起始
id
3
(或
4
)时,输出包含
5
,但
5
不是
3
(或
4
)的祖先或后代-它位于层次结构的单独分支中。抱歉,如果我的描述不清楚的话。当起始id为3时。那么它的父级是2。2是3和5的父级。整个想法是我从表中随机抽取id。然后把这个id给所有的孩子和他们的孩子。还有所有的父母和那些父母的孩子。谢谢!结果按预期工作,类似于我在编辑零件后的初始问题后的查询。但是,有没有一种方法可以以某种方式使用此查询,使其成为视图,并且给定id=2和parent_id=2不在查询中。这意味着结果将用于例如:列,其中结果是用于那些id和父id的值。@j请不要使用带有动态输入值的视图,否。谢谢您的解决方案。它确实帮助我达到了预期的效果。