【发布时间】:2015-11-04 03:50:41
【问题描述】:
我正在使用 SQL Server 2014 Express 在 AdventureWorks2012 数据库中学习递归 CTE。我想我主要得到下面的例子(取自Beginning T-SQL 3rd Edition),但我不太明白为什么递归CTE不会产生重复。
以下是我试图理解的递归 CTE,它是标准的员工 - 经理层次结构。
;with orgchart (employeeid, managerid, title, level, node) as (
--Anchor
select employeeid
, managerid
, title
, 0
, convert(varchar(30),'/') 'node'
from employee
where managerid is null
union all
--Recursive
select emp.employeeid
, emp.managerid
, emp.title
, oc.level + 1
, convert(varchar(30), oc.node + convert(varchar(30),emp.managerid) + '/')
from employee emp
inner join orgchart oc on oc.employeeid = emp.managerid
)
select employeeid
, managerid
, space(level * 3) + title 'title'
, level
, node
from orgchart
order by node;
它工作正常,但是当我尝试通过临时表重新创建它来了解发生了什么时,问题就来了。我创建了一系列临时表,将一个输出插入到下一个查询的输入中,并重新创建递归 CTE 所做的事情。
--Anchor (Level 0)
select employeeid
, managerid
, title
, 0
, convert(varchar(30),'/') 'node'
into #orgchart
from employee
where managerid is null
然后我使用该临时表重新创建第一级递归,此时它只是递归 CTE,但带有临时表。
--Anchor + 1 level
select *
into #orgchart2
from #orgchart
union all
select emp.employeeid
, emp.managerid
, emp.title
, oc.level + 1
, convert(varchar(30), oc.node + convert(varchar(30),emp.managerid) + '/')
from employee emp
inner join #orgchart oc on oc.employeeid = emp.managerid
到目前为止一切顺利,结果很有意义。然后我再做一次,但这就是它开始崩溃的地方:
--Anchor + 2 levels
select *
into #orgchart3
from #orgchart2
union all
select emp.employeeid
, emp.managerid
, emp.title
, oc.level + 1
, convert(varchar(30), oc.node + convert(varchar(30),emp.managerid) + '/')
from employee emp
inner join #orgchart2 oc on oc.employeeid = emp.managerid
由此的输出开始返回级别 1 员工的重复行(所有字段重复)。这是有道理的 - UNION ALL 之后的第二个查询将返回以前的级别以及新的递归级别,并且 UNION ALL 不会重复。如果我再做一轮递归,那么 2 级员工也会重复,以此类推。
我知道我可以将 UNION ALL 更改为 UNION 以删除重复项,但我想了解为什么递归 CTE 也不会产生重复项?它使用 UNION ALL,所以我不明白重复数据删除的来源。删除重复项是递归 CTE 的固有部分吗?
我正在尝试发布所有结果集,但如果需要它们来理解问题,请告诉我,我会发布它们。提前致谢。
【问题讨论】:
-
你不是用SQL中的union自己造成了重复吗?如果您删除它,您应该只将正确的项目放入临时文件中。表,然后合并结果。
标签: sql-server tsql recursion duplicates sql-server-2014