Sql 从单个oracle表中查找分层或父子列值
我有一个表名tree,它有两列,一列是p,第二列是chSql 从单个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”作为输入,我必须找到所有父元素
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上运行时没有给出任何结果。我按原样运行