从表示树结构的Oracle表中选择所有后代行

时间:2011-01-17 20:16:04

标签: sql oracle oracle10g hierarchical-data recursive-query

我在Oracle 10g中有一个表MYTYPE表示树结构,如下所示:

ID | PARENTID | DETAIL

我想选择MYTYPE中作为特定ID后代的所有行,这样我就可以在其他地方创建查询,例如:

SELECT * 
  FROM MYDETAIL 
 WHERE MYTYPEID IN [all MYTYPE which are descendants of some ID];

建立后代集的成本效益方法是什么,最好不使用PL / SQL?

4 个答案:

答案 0 :(得分:8)

Oracle不支持在11g R2之前使用递归子查询因子(SQL Server语法中的CTE)的ANSI分层语法,因此您必须使用Oracle的本机CONNECT BY语法(从v2开始支持):

   SELECT t.*
      FROM MYTABLE t
START WITH t.parentid = ?
CONNECT BY PRIOR t.id = t.parentid

将问号替换为您想要查找基于的分层数据的父级。

参考:

答案 1 :(得分:2)

使用RDBMS中的ID,ParentID列管理分层数据称为Adjacency List模型。虽然非常容易实现和维护(即插入,更新,删除),但确定谱系(即祖先和后代)的成本很高。正如其他答案已经写好的那样,Oracle的CONNECT BY会起作用,但这是一项昂贵的操作。您可能最好以不同方式表示数据。

对于您的情况,最简单的解决方案可能是在您的架构中添加所谓的Hierarchy Bridge表,并在原始表中添加LEVEL列。该表具有列ID,DescendantID,其中选择ID给出所有后代记录,并且通过DescentantID选择给出所有祖先记录。基表上需要LEVEL来订购记录。通过这种方式,您可以权衡廉价读取的昂贵更新,这正是您的问题所暗示的。

涉及更改基础数据的其他可能性包括嵌套集和物化路径表示。对于更便宜的读取,这提供了更昂贵的写入的类似权衡。有关选项的完整列表,优缺点以及一些实施说明see my previous question on the topic

答案 2 :(得分:1)

Oracle可以执行递归查询。 尝试查看start with ... connect by,如下所示:

Select *
from MYDETAIL
Starting with PARENTID= 1 --or whatever the root ID is
connect by PARENTID = prior ID

http://psoug.org/reference/connectby.html

答案 3 :(得分:1)

以下是oracle中“connect by”功能的详细信息。 http://psoug.org/reference/connectby.html