--导入数据 create table dbo.dt_user ( UserID int, ManagerID int, Name Nvarchar(10) ) insert into dbo.dt_user select 1,-1,N'Boss' union all select 11,1,N'A1' union all select 12,1,N'A2' union all select 13,1,N'A3' union all select 111,11,N'B1' union all select 112,11,N'B2' union all select 121,12,N'C1'
--CTE的简单例子 with cte as ( select UserID,ManagerID,name,name as ManagerName from dbo.dt_user where ManagerID=-1 union ALL select c.UserID,c.ManagerID,c.Name,p.name as ManagerName from cte P inner join dbo.dt_user c on p.UserID=c.ManagerID ) select UserID,ManagerID,Name,ManagerName from cte order by UserID
1.递归查询至少包含两个子查询
第一个子查询称作定点(Anchor)子查询:定点查询只是一个返回有效表的查询,用于设置递归的初始值;
第二个子查询称作递归子查询:该子查询调用CTE名称,触发递归查询,实际上是递归子查询调用递归子查询;
两个子查询使用union all,求并集;
2.CTE的递归终止条件
递归查询没有显式的递归终止条件,只有当递归子查询返回空结果集(没有数据行返回)或是超出了递归次数的最大限制时,才停止递归。
3.递归步骤
step1:定点子查询设置CTE的初始值,即CTE的初始值Set0;递归调用的子查询过程:递归子查询调用递归子查询;
step2:递归子查询第一次调用CTE名称,CTE名称是指CTE的初始值Set0,第一次执行递归子查询之后,CTE名称是指结果集Set1;
step3:递归子查询第二次调用CTE名称,CTE名称是指Set1,第二次执行递归子查询之后,CTE名称是指结果集Set2;
step4:在第N次执行递归子查询时,CTE名称是指Set(N-1),递归子查询都引用前一个递归子查询的结果集;
Step5:如果递归子查询返回空数据行,或超出递归次数的最大限制,停止递归;
--查询所有子节点 WITH FCTE AS ( SELECT ContentId,FatherContentId,0 as Level FROM ProductSeries_Content AS PSC WHERE FatherContentId = 1 UNION ALL SELECT b.ContentId,b.FatherContentId,a.Level+1 as Level FROM FCTE AS a INNER JOIN ProductSeries_Content AS b ON a.ContentId = b.FatherContentId ) SELECT * FROM FCTE --查询所有父节点 WITH TCTE AS ( SELECT ContentId,FatherContentId FROM ProductSeries_Content AS PSC WHERE ContentId = 260 UNION ALL SELECT b.ContentId,b.FatherContentId FROM TCTE AS a INNER JOIN ProductSeries_Content AS b ON a.FatherContentId = b.ContentId ) SELECT * FROM TCTE --补充2点 --The statement terminated. The maximum recursion 100 has been exhausted before statement completion. --递归次数超过100次,要设置递归次数限制 OPTION(MAXRECURSION 0) --注意!注意!注意! ContentId的值不能等于FatherContentId,这样数据会无限递归