【发布时间】:2011-11-30 11:34:02
【问题描述】:
我有一个 Oracle 表中的数据,该表被组织为一个可以包含循环的图形(参见示例)。
CREATE TABLE T (parent INTEGER, child INTEGER)
AS select 1 parent, 2 child from dual
union all select 1 parent, 8 child from dual
union all select 2 parent, 3 child from dual
union all select 2 parent, 4 child from dual
union all select 2 parent, 8 child from dual
union all select 3 parent, 4 child from dual
union all select 3 parent, 6 child from dual
union all select 4 parent, 5 child from dual
union all select 5 parent, 8 child from dual
union all select 6 parent, 5 child from dual
union all select 7 parent, 3 child from dual
union all select 7 parent, 5 child from dual
union all select 8 parent, 6 child from dual
我的目标是获取节点 X 的所有后代节点(子节点、子节点的子节点等)。假设是 2。我的预期结果是:3、4、5、6、8。
我知道我可以设计这样的查询:
SELECT child, sys_connect_by_path(child,'/')
FROM T
START WITH parent = 2
CONNECT BY NOCYCLE PRIOR child = PARENT;
这样一个查询的问题是它会遍历所有可能的路径,直到它们循环,并且在我的实际数据中它们太多了。结果包含许多重复项 - 这是:
child | sys_connect_by_path (for information)
3 | /3
4 | /3/4
5 | /3/4/5
8 | /3/4/5/8
6 | /3/4/5/8/6
6 | /3/6
5 | /3/6/5
8 | /3/6/5/8
4 | /4
5 | /4/5
8 | /4/5/8
6 | /4/5/8/6
8 | /8
6 | /8/6
5 | /8/6/5
我的实际数据要复杂得多。执行此类查询的成本非常高,以至于我的可自动扩展的 TEMP 表空间达到 10Gb(最初为 500 Mb),而我的数据库实际上因磁盘已满而损坏。
我试图设计这样的查询(递归 WITH 子句):
WITH descendants(node) AS
( SELECT 2 node FROM dual
UNION ALL
(
SELECT child
FROM T
INNER JOIN descendants D
ON T.parent = D.node
MINUS SELECT node FROM descendants
)
)
SELECT * FROM descendants
我遇到的问题是:
- 在 Oracle 10g 中,这没有实现(
ORA-32033: unsupported column aliasing,有些客户使用 Oracle 9 或 10), - 使用 Oracle 11g,我得到
ORA-32041: UNION ALL operation in recursive WITH clause must have only two branches。如果我删除 MINUS 子句,我会得到循环(ORA-32044: cycle detected while executing recursive WITH query)。
您将如何查询我的原始数据以有效地获取节点 3、4、5、6、8?也欢迎 PL/SQL 解决方案。
谢谢。
【问题讨论】:
标签: sql oracle data-structures plsql