Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.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
Sql 从单个oracle表中查找分层或父子列值_Sql_Oracle_Parent Child_Hierarchical Query - Fatal编程技术网

Sql 从单个oracle表中查找分层或父子列值

Sql 从单个oracle表中查找分层或父子列值,sql,oracle,parent-child,hierarchical-query,Sql,Oracle,Parent Child,Hierarchical Query,我有一个表名tree,它有两列,一列是p,第二列是ch p ch ------------- 1 2 1 3 1 4 2 5 2 6 7 8 9 10 11 12 6 13 13 14 14 15 14 16 我想要的输出是所有链接到父级的子级。如果我将“1”作为输入,我必须找到所有父元素

我有一个表名tree,它有两列,一列是p,第二列是ch

p       ch 
-------------
1       2                   
1       3 
1       4 
2       5 
2       6 
7       8 
9       10 
11      12 
6       13 
13      14 
14      15 
14      16
我想要的输出是所有链接到父级的子级。如果我将“1”作为输入,我必须找到所有父元素和子元素,例如,在这种情况下,1是2、3、4的父元素,2是5的父元素,依此类推……在这种情况下,我需要每个链接的子元素和父元素本身,如下所述:

ParentChilds
------------
1
2
3
4
5
6
13
14
15
16
下面是我编写的查询,我想确认这是最好的解决方案,或者我们可以用更好的方法来实现,因为我的表中有大量数据:

with LinkedAccounts (p, ch, orig_recur, dest_recur, lvl) as (
            select n.p
    , n.ch
    , 1 orig_recur
     , case n.p
           when 1 then ch
                   else p
        end dest_recur
     , 1 lvl
   from tree n
 where n.p = 1
   or n.ch = 1 union all
select n.p
     , n.ch
    , LinkedAccounts.dest_recur orig_recur
     , case n.p
         when LinkedAccounts.dest_recur then n.ch
                           else n.p
       end dest_recur
     , LinkedAccounts.lvl + 1 lvl
  from LinkedAccounts
  join tree n
        on (n.p = LinkedAccounts.dest_recur and n.ch != LinkedAccounts.orig_recur)
        or (n.ch = LinkedAccounts.dest_recur and n.p != LinkedAccounts.orig_recur)
)
 search breadth first by orig_recur, dest_recur set ordering
cycle ch,
 p set is_cycle to '1' default '0'   select distinct p    from LinkedAccounts    union     Select Distinct ch    from LinkedAccounts;

这种方法可能更容易理解,因为它使用了一种更传统的递归cte方法,从根开始,将每个父级连接到它的子级。根节点被标识为那些本身没有父节点的节点(
,其中不存在


另一方面,层次结构中的命名约定是不寻常的-
ch
通常是
nodeid
(但是
parent
将是parent/parentid)-这将建模一个节点,允许在节点上添加列。乍一看,您似乎是在模拟连接关系本身,而不是节点?

使用分层查询:

Oracle 11g R2架构设置

CREATE TABLE TREE ( p, ch ) AS
          SELECT  1,  2 FROM DUAL
UNION ALL SELECT  1,  3 FROM DUAL
UNION ALL SELECT  1,  4 FROM DUAL
UNION ALL SELECT  2,  5 FROM DUAL
UNION ALL SELECT  2,  6 FROM DUAL
UNION ALL SELECT  7,  8 FROM DUAL
UNION ALL SELECT  9, 10 FROM DUAL
UNION ALL SELECT 11, 12 FROM DUAL
UNION ALL SELECT  6, 13 FROM DUAL
UNION ALL SELECT 13, 14 FROM DUAL
UNION ALL SELECT 14, 15 FROM DUAL
UNION ALL SELECT 14, 16 FROM DUAL
UNION ALL SELECT  2,  1 FROM DUAL;
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            3 |
|            4 |
|            5 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
查询1

CREATE TABLE TREE ( p, ch ) AS
          SELECT  1,  2 FROM DUAL
UNION ALL SELECT  1,  3 FROM DUAL
UNION ALL SELECT  1,  4 FROM DUAL
UNION ALL SELECT  2,  5 FROM DUAL
UNION ALL SELECT  2,  6 FROM DUAL
UNION ALL SELECT  7,  8 FROM DUAL
UNION ALL SELECT  9, 10 FROM DUAL
UNION ALL SELECT 11, 12 FROM DUAL
UNION ALL SELECT  6, 13 FROM DUAL
UNION ALL SELECT 13, 14 FROM DUAL
UNION ALL SELECT 14, 15 FROM DUAL
UNION ALL SELECT 14, 16 FROM DUAL
UNION ALL SELECT  2,  1 FROM DUAL;
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            3 |
|            4 |
|            5 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |

CREATE TABLE TREE ( p, ch ) AS
          SELECT  1,  2 FROM DUAL
UNION ALL SELECT  1,  3 FROM DUAL
UNION ALL SELECT  1,  4 FROM DUAL
UNION ALL SELECT  2,  5 FROM DUAL
UNION ALL SELECT  2,  6 FROM DUAL
UNION ALL SELECT  7,  8 FROM DUAL
UNION ALL SELECT  9, 10 FROM DUAL
UNION ALL SELECT 11, 12 FROM DUAL
UNION ALL SELECT  6, 13 FROM DUAL
UNION ALL SELECT 13, 14 FROM DUAL
UNION ALL SELECT 14, 15 FROM DUAL
UNION ALL SELECT 14, 16 FROM DUAL
UNION ALL SELECT  2,  1 FROM DUAL;
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            3 |
|            4 |
|            5 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
查询2

CREATE TABLE TREE ( p, ch ) AS
          SELECT  1,  2 FROM DUAL
UNION ALL SELECT  1,  3 FROM DUAL
UNION ALL SELECT  1,  4 FROM DUAL
UNION ALL SELECT  2,  5 FROM DUAL
UNION ALL SELECT  2,  6 FROM DUAL
UNION ALL SELECT  7,  8 FROM DUAL
UNION ALL SELECT  9, 10 FROM DUAL
UNION ALL SELECT 11, 12 FROM DUAL
UNION ALL SELECT  6, 13 FROM DUAL
UNION ALL SELECT 13, 14 FROM DUAL
UNION ALL SELECT 14, 15 FROM DUAL
UNION ALL SELECT 14, 16 FROM DUAL
UNION ALL SELECT  2,  1 FROM DUAL;
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            3 |
|            4 |
|            5 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |

CREATE TABLE TREE ( p, ch ) AS
          SELECT  1,  2 FROM DUAL
UNION ALL SELECT  1,  3 FROM DUAL
UNION ALL SELECT  1,  4 FROM DUAL
UNION ALL SELECT  2,  5 FROM DUAL
UNION ALL SELECT  2,  6 FROM DUAL
UNION ALL SELECT  7,  8 FROM DUAL
UNION ALL SELECT  9, 10 FROM DUAL
UNION ALL SELECT 11, 12 FROM DUAL
UNION ALL SELECT  6, 13 FROM DUAL
UNION ALL SELECT 13, 14 FROM DUAL
UNION ALL SELECT 14, 15 FROM DUAL
UNION ALL SELECT 14, 16 FROM DUAL
UNION ALL SELECT  2,  1 FROM DUAL;
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 1
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            3 |
|            4 |
|            5 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |
SELECT     p AS ParentChilds
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     ch
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE PRIOR ch = p
UNION
SELECT     p
FROM       TREE
START WITH p = 6
CONNECT BY NOCYCLE ch = PRIOR p
| PARENTCHILDS |
|--------------|
|            1 |
|            2 |
|            6 |
|           13 |
|           14 |
|           15 |
|           16 |

您的查询适用于根节点,但在内部节点上失败(尝试节点6,您将看到1和2不在结果中,它们必须在结果中,因为它们是6的祖先)。+1作为您的答案。是的,您的查询很好,现在我有另一个条件,我可以将数据2作为父节点,1作为子节点。我只是检查了一下我的表,发现了这样的数据。因此,在本例中,“ORA-01436:CONNECT BY loop in user data”错误即将出现,我读取到CONNECT BY与@AnkurBhutani相比性能较差-编辑-将
NOCYCLE
添加到查询中以防止循环。如果您担心性能,那么编写这两种方法,并根据您的数据分析它们,然后选择最佳方法。数据、索引、统计数据等的结构将影响哪个性能更好,其他人无法回答。我在sqlfiddle上试过,它在那里工作,但在Sql developer上运行时没有给出任何结果。我按原样运行