参考博客:https://www.cnblogs.com/ljhdo/p/4580347.html

简介

递归查询主要应用于层级结构表的查询:

  • 叶节点-> 根节点的查询
  • 根节点-> 叶节点的查询

递归查询必须满足的条件

初始条件

递归查询至少包含两个子查询两个子查询使用union all,求并集

  1. 第一个子查询称作定点(Anchor)子查询:定点查询只是一个返回有效表的查询,用于设置递归的初始值
  2. 第二个子查询称作递归子查询:触发递归查询,实际上是递归子查询调用递归子查询

终止条件

  • 递归查询没有显式的递归终止条件,
  • 只有当递归子查询返回空结果集(没有数据行返回)或是超出了递归次数的最大限制时,才停止递归
  • 默认的递归查询次数是100,可以使用查询提示(hint):MAXRECURSION 控制递归的最大次数:OPTION( MAXRECURSION 16);如果允许无限制的递归次数,使用查询提示:option(maxrecursion 0);当递归查询达到指定或默认的 MAXRECURSION 数量限制时,SQL Server将结束查询并返回错误,如下:
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
  • 事务执行失败,该事务包含的所有操作都被回滚。在产品环境中,慎用maxrecursion 查询提示,推荐通过 where 条件限制递归的次数。

递归调用表达式

  1. 定点子查询设置CTE的初始值,即CTE的初始值Set0递归调用的子查询过程:递归子查询调用递归子查询
  2. 递归子查询第一次调用CTE名称,CTE名称是指CTE的初始值Set0第一次执行递归子查询之后,CTE名称是指结果集Set1
  3. 递归子查询第二次调用CTE名称,CTE名称是指Set1,第二次执行递归子查询之后,CTE名称是指结果集Set2;
  4. 在第N次执行递归子查询时,CTE名称是指Set(N-1),递归子查询都引用前一个递归子查询的结果集;
  5. 如果递归子查询返回空数据行,或超出递归次数的最大限制,停止递归

递归查询示例

创建测试数据

创建一张临时表manager_user,其中ManagerID是UserID的父节点,UserID是ManagerID的子节点

create table #manager_user
(UserID int,ManagerID int,Name Nvarchar(10)
)insert into #manager_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'

其结果展示如下图所示:

查询每个User的的直接上级Manager

  1. 查询ManagerID=-1,作为root node,这是递归查询的起始点。
  2. 迭代公式是 union all 下面的查询语句。在查询语句中调用中cte,而查询语句就是cte的组成部分,即 “自己调用自己”,这就是递归的真谛所在。所谓迭代,是指每一次递归都要调用上一次查询的结果集,Union ALL是指每次都把结果集并在一起。
  3. -N,迭代公式利用上一次查询返回的结果集执行特定的查询,直到CTE返回null 或达到最大的迭代次数,默认值是32。最终的结果集是迭代公式返回的各个结果集的并集,求并集是由Union All 子句定义的,并且只能使用Union ALL。
with cte as
(
select UserID,ManagerID,name,name as ManagerName
from #manager_user
where ManagerID=-1union allselect c.UserID,c.ManagerID,c.Name,p.name as ManagerName
from cte P
inner join #manager_user con p.UserID=c.ManagerID
)
select UserID,ManagerID,Name,ManagerName
from cte
order by UserID

其结果展示为:

查询路径,在层次结构中查询子节点到父节点的path

with cte as
(
select UserID,ManagerID,name,cast(name as nvarchar(max)) as ReportPath
from #manager_user
where ManagerID=-1union all
select c.UserID,c.ManagerID,c.Name,c.name+'->'+p.ReportPath as ReportPath
from cte P
inner join #manager_user con p.UserID=c.ManagerID
)
select UserID,ManagerID,Name,ReportPath
from cte
order by UserID

其结果展示为:

实现由父级向子级的查询

要想获取ManagerID的所有UserID等信息,必须使用递归查询

下列sql展示的是ManagerId =1的所有相关子节点

with cte(UserId,ManagerID,Name) as
(
select *
from #manager_user
where UserId=1union all
select h.*
from #manager_user h
inner join cte c on h.ManagerID=c.UserId
--where c.UserId!=h.UserId
)
select *
from cte
order by ManagerID

其查询结果为:

如果要查看向内递归到多少level,可以使用派生列

下列sql展示的是ManagerId =1的所有相关子节点以及递归到多少level

with cte(UserId,ManagerId,Name,Level) as
(
select UserId,ManagerId,Name,0 as Level
from #manager_user
where UserId=1union all
select h.UserId,h.ManagerId,h.Name,c.Level+1 as Level
from #manager_user h
inner join cte c on h.ManagerId=c.UserId
--where c.UserId!=h.UserId
)
select *
from cte
order by ManagerId

其结果展示为:

由子级向父级的递归查询

下列sql展示的是UserId =121的所有相关父节点

with cte as
(
select UserId,ManagerId,name
from #manager_user
where UserId= 121union all
select h.UserId,h.ManagerId,h.name
from #manager_user h
inner join cte c on h.UserId=c.ManagerId
)
select UserId,ManagerId,name
from cte
order by ManagerId

其结果展示为:

[SQL Server] TSQL实现SQL Server中CTE 递归查询相关推荐

  1. cte公用表表达式_CTE SQL删除; 在SQL Server中删除具有公用表表达式的数据时的注意事项

    cte公用表表达式 In this article, the latest in our series on Common table expressions, we'll review CTE SQ ...

  2. SQL Server CTE 递归查询全解

    在TSQL脚本中,也能实现递归查询,SQL Server提供CTE(Common Table Expression),只需要编写少量的代码,就能实现递归查询,本文详细介绍CTE递归调用的特性和使用示例 ...

  3. sql游标 while_用SQL Server中的排名函数替换SQL While循环和游标,以提高查询性能

    sql游标 while SQL While loop and cursor are the most common approach to repeat a statement on conditio ...

  4. SQL Server 2014新功能 -- 内存中OLTP(In-Memory OLTP)

    概述 内存中OLTP(项目"Hekaton")是一个全新的.完全集成到SQL Server的数据库引擎组件. 对OLTP工作负载访问中在内存中的数据进行了优化.内存中OLTP能够帮 ...

  5. sql server新增列_SQL Server 2017中的新增功能

    sql server新增列 SQL Server 2017 is considered a major release in the history of the SQL Server life cy ...

  6. sql azure 语法_Azure Data Studio中SQL Server Profiler

    sql azure 语法 In this article, we will explore SQL Server Profiler in Azure Data Studio in detail inc ...

  7. sql server锁异常_SQL Server中异常处理的背景

    sql server锁异常 RAISERROR statement. RAISERROR语句. Figure 1 demonstrates a combination of mandatory par ...

  8. sql server新增列_SQL Server 2016安装中的新增功能?

    sql server新增列 SQL Server 2016 introduced officially on the 1st of June 2016. It comes with many new ...

  9. sql azure 语法_Azure Data Studio中SQL Server架构比较扩展

    sql azure 语法 This article explores the SQL Server Schema Compare extension in the Azure Data Studio. ...

最新文章

  1. Elasticsearch搜索类型讲解(QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCH和DFS_QUERY_AND_FEATCH)...
  2. java经典模式:七种模式样例
  3. CODEVS 3288 积木大赛
  4. 解决无法删除的dll文件
  5. 丹佛斯冷媒尺汉化下载_制冷系统十大仿真软件!制冷百家网下载
  6. 异常处理——Another app is currently holding the yum lock
  7. HTML5表单新增元素与属性(form、formaction、formmethod、formenctype、formtarget、autofous、required、labels)
  8. Python的矩阵分块
  9. Linux下C语言编程(1):IO编程
  10. Windows XP 启动NetMeeting
  11. 新安装IAR打开现有工程
  12. android 蓝牙信息提醒,Android蓝牙与BLE通信相关的读、写、通知、指示操作
  13. 笔记本扩展显示器,微信界面显示字体模糊如何解决?
  14. 学习Python会用到的8个软件,你用的哪些
  15. 机器学习核心算法各个击破
  16. 御坂御坂题解(出自北航校赛) 约瑟夫环问题高效解决方案
  17. 6:求指定范围内的素数
  18. Mysql使用函数json_extract处理Json类型数据
  19. 卓海科技冲刺创业板:拟募资5.47亿 相宇阳控制52.9%股权
  20. Python爬虫实战(1) | 爬取豆瓣网排名前250的电影(上)

热门文章

  1. 在office中,使用office的宏合并excel表格
  2. html如何嵌套使用注释
  3. 使用pygal_maps_world.i18n中数据画各大洲地图
  4. 做游戏3D建模师必须加班熬夜吗?这个职业对新人到底友不友好?
  5. 收藏:WORD中快速输入下分割线
  6. 蔡康永的一些文字(转)
  7. php继承 重写方法吗,php中如何重写一个方法呢?
  8. 【qstock量化】数据篇之股票基本面数据
  9. 北京林业大学C语言测试,北京林业大学c语言题库上机题一
  10. 爆料,华为重回深圳,深圳第二个硅谷来了-龙华九龙山未来可期