SQL递归记录:如何折叠到“仅一级”?

时间:2012-01-04 13:44:25

标签: sql sql-server oracle recursion firebird

我有一个带有项目ID和'inherit id'的记录,即当前项目继承的项目。继承级别未知。

我现在需要将其折叠为:'从最顶层继承'

E.g:

1006 <- 1005 <- 1002 <- 999

prj_id / inherit_id

999  / 1002

1002 / 1005

1005 / 1006

应该崩溃到

1006 <- 1005 

1006 <- 1002

1006 <- 999

prj_id / inherit_id

999  / 1006

1002 / 1006

1005 / 1006

这可以在没有循环的SQL语句中完成吗? 创建临时表很好。 它适用于FireBird,SQL Server,Oracle 9+(即3组语句都可以)

我只有这么远:

从继承自己的记录继承的记录:

select tt_prj_id,tt_name,tt_inherit_id from tt_prj a

where a.tt_inherit_id in

(select tt_prj_id from tt_prj b

 where b.tt_inherit_id is not null

 and b.tt_inherit_id > 0)

谁可以帮助我?

3 个答案:

答案 0 :(得分:6)

以下内容应该让你开始(这不是最终解决方案!):

with recursive project_tree as (
   select tt_prj_id, cast(tt_prj_id as varchar(500))||'/' as id_path, tt_prj_id as root_id
   from tt_prj
   where tt_inherit_id = 0

   union all

   select c.tt_prj_id, id_path || cast(c.tt_prj_id as varchar(100)) ||'/', null
   from tt_prj c
     join project_tree p on c.tt_inherit_id = p.tt_prj_id
)
select *
from project_tree;

这适用于Firebird 2.5(可能也适用于2.1,但我现在手头没有)

当你删除关键字recursive(这是ANSI标准所要求的,但是从什么时候开始关心那个...)并且你需要替换标准字符串连接时,它应该与SQL Server一起使用{使用||运算符{1}}。

Oracle在11.2之前只支持递归CTE。 在以前的版本中,您需要使用+重写此内容,这可能是这样的:

CONNECT BY

答案 1 :(得分:1)

transitive closure tablesnested sets上进行搜索。它们的结构使得有效查询关系数据成为可能,但它需要对插入/更新/删除进行更多维护,并且关闭表将需要存储额外的记录(权衡空间以提高效率)。

答案 2 :(得分:1)

用户a_horse_with_no_name是正确的。可以使用递归CTE执行此操作。查看此链接以获取更多信息。

http://blog.sqlauthority.com/2008/07/28/sql-server-simple-example-of-recursive-cte/

再一次,Pinal Dave ftw。