Oracle中的分层查询

时间:2012-05-22 14:50:09

标签: sql oracle hierarchical-data

我在Oracle11g中有一个像(id,parent_id)这样的结构的表。

id    parent_id
---------------
1     (null)
2     (null)
3     1
4     3
5     3
6     2
7     2

我想查询它以获得与这些id中的每一个分层链接的所有行,因此结果应为:

root_id  id    parent_id
------------------------
1        3     1
1        4     3
1        5     3
2        6     2
2        7     2
3        4     3
3        5     3

我已经在connect bystart with挣扎了很长一段时间了,我所能得到的只是我想要的结果的一小部分,例如:

select connect_by_root(id) root_id, id, parent_id from my-table
start with id=1
connect by prior id = parent_id

我不想使用任何for循环来获得完整的结果。

任何想法?

祝你好运, JérômeLefrère

PS:在第一次回答后编辑,注意到我忘记了一些我想要的结果......

3 个答案:

答案 0 :(得分:3)

您发布的查询缺少from子句,并在connect_by_root之外留下了下划线,但我认为这些不是您问题的根源。

以下查询为您提供了您正在寻找的结果:

select * from (
   select connect_by_root(id) root_id, id, parent_id
   from test1
   start with parent_id is null
   connect by prior id = parent_id)
where root_id <> id

核心问题是您指定了一个特定的值来开始,而是指定一种识别根行的方法。将id = 1更改为parent_id is null可以返回表格的全部内容。

我还添加了外部查询来过滤结果集中的根行,这在您的问题中未提及,但显示在您想要的结果中。

SQL Fiddle Example


评论回复:

在提供的版本中,您确实获得id = 3的后代,但不是3是根的方式。这是因为我们从绝对的根开始。解决这个问题很容易,只需省略start with子句:

SELECT *
FROM
  (SELECT connect_by_root(id) root_id,
          id,
          parent_id
   FROM test1
CONNECT BY
   PRIOR id = parent_id)
WHERE root_id <> id

SQL Fiddle Example

答案 1 :(得分:2)

试试这个:

select connect_by_root(id) root_id, id, parent_id
from your_table
start with parent_id is null
connect by prior id = parent_id

答案 2 :(得分:0)

它将为您提供所需的确切结果:

select connect_by_root(id) as root, id, parent_id
from test1
connect by prior id=parent_id
start with parent_id is not null;