SQL 递归查询,意淫CTE递归的执行步骤
今天用到了sql的递归查询。递归查询是CTE语句with xx as(....)实现的。
假如表Category数据如下。

我们想查找机枪这个子分类极其层次关系(通过子节点,查询所有层级节点)。以下是查询语句
WITH tt AS ( SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=15 --定位点成员
UNION ALL
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId --递归成员 ) SELECT * FROM tt
执行结果

CTE递归说明:
上面的脚本,我注明了定位点成员,和递归成员。
定位点成员形成了查询的基本结果集。其实就是你用于查询的"引子"数据。在递归cte开始执行时,第一次执行,会先执行定位成员,并得到寄出结果集。
递归成员是每次递归执行的语句。个人意淫,每次递归时,是把上一次递归查询得出的结果集传递给递归语句,并继续执行递归
在递归时,如果上一次查询没有返回结果集,则终止递归。(这点让我纠结很久,因为没有显示的著名何时结束递归~)
意淫的执行步骤--------------------
首先执行定位成员:
SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46
并得到了结果集:

然后执行第一次递归:
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId
执行递归时,join了 cte 语句本身,就是tt,join里的语句跟with as里的语句一样。其实语句可以意淫成酱紫
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
--SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=15 华丽的忽略掉了
--UNION ALL 华丽的忽略掉了
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId --我们继续递归~ )tt ON tt.Parent=c.CategoryId
这次递归可以拆分成两个操作,查询结果和继续递归。
1.因为是第一次递归,所以将执行定位成员得出的结果集带入,进行查询。其实执行的是酱紫
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46 )tt ON tt.Parent=c.CategoryId
发现有结果:

则继续进行递归:
递归时语句还是酱紫:
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
--SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=15 华丽的忽略掉了
--UNION ALL 华丽的忽略掉了
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN tt ON tt.Parent=c.CategoryId --我们继续递归 )tt ON tt.Parent=c.CategoryId
这次递归查询,所用的结果集是上次递归查询得出的(不再是定位成员的结果集了)。就是用的下面这个结果集

执行语句是酱紫的
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46 )tt ON tt.Parent=c.CategoryId
)tt ON tt.Parent=c.CategoryId
第一层join的数据是上次递归查询的语句。
发现有结果:

ok继续递归吧
继续上面的步骤,带入上次查询的结果集进行查询。
执行语句其实是酱紫:
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
SELECT c.CategoryId,c.Name,c.Parent,tt.level+1 level FROM Category c JOIN
(
SELECT CategoryId,Name,Parent,0 level FROM dbo.Category WHERE CategoryId=46 )tt ON tt.Parent=c.CategoryId
)tt ON tt.Parent=c.CategoryId
)tt ON tt.Parent=c.CategoryId
得出的结果集:

啥也木有,终止递归。
然后用union all 把每次递归的结果集合起来。得出了最终的查询结果。
这个步骤是意淫的,我还设想了其他的方式。但在终止递归上都存在问题,所以最终把文章写成酱紫。
参考文章:https://www.cnblogs.com/youngmin/p/6256478.html
SQL 递归查询,意淫CTE递归的执行步骤的更多相关文章
- SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用
本文出处:http://www.cnblogs.com/wy123/p/5960825.html 我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等 ...
- TSql CTE 递归原理探究
CTE是如何进行递归的?产生递归的条件有三个,分别是 初始值 自身调用自身 结束递归的条件 1,示例代码 ;with cte as ( as jd union all as jd from cte ) ...
- 【转】sql递归查询问题
原文链接地址http://www.cnblogs.com/sweting/archive/2009/06/08/1498483.html 在工作中遇到一个问题,是需要sql递归查询的.不懂,于是到cs ...
- SQL递归查询(with as)
SQL递归查询(with cte as) with cte as( select Id,Pid,DeptName,0 as lvl from Department where Id = 2 ...
- SQL Server封闭掉 触发器递归
SQL Server关闭掉 触发器递归SQL Server 是有一个开关, 可以关闭掉 触发器递归的.EXEC sp_dboption '数据库名字', 'recursive triggers', ...
- SQL语句在查询分析器中可以执行,代码中不能执行
问题:SQL语句在查询分析器中可以执行,代码中不能执行 解答:sql中包含数据库的关键字,将关键字用[]括起来,可以解决. 后记:建数据库的时候尽量避免使用关键字. 例子: sql.Format(&q ...
- sql语句or与union all的执行效率比较
看到一篇文章是讲sql语句or与union all的执行效率比较的,以前没怎么注意这个问题,感觉文章写的不错,转来一看. 文章原链接:http://www.cunyoulu.com/zhuanti/q ...
- SQL语句在数据库中是如何执行的
第一步:应用程序把查询SQL语句发给服务器端执行 我们在数据层执行SQL语句时,应用程序会连接到相应的数据库服务器,把SQL语句发送给服务器处理. 第二步:服务器解析请求的SQL语句 SQL计划缓存, ...
- jQuery使用伪递归重复执行动画
使用setInterval()来重复执行动画,会因为动画执行过程的时候,setInterval()的时间依然是在走的,所以会导致动画的调用时间不理想,因此只能使用递归来重复执行动画. // 首页LOG ...
随机推荐
- 【FFMEPG】windows下编译ffmpeg2.5——使用VS2013,ARMLINUX,ANDORID编译ffmpeg
原文:http://blog.csdn.net/finewind/article/details/42784557 一.准备: 1. 本机环境: win7 64bit: 2. 安装MinGW到C:\M ...
- ML.NET 1
ML.NET 示例:目录 ML.NET 示例中文版:https://github.com/feiyun0112/machinelearning-samples.zh-cn英文原版请访问:https:/ ...
- 【转】MySql 三大知识点——索引、锁、事务
索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序.2. 快速查找. 索引的缺点:1. 占用空间.2. 降低更新表的速度. 注意点:小表使用全表扫描更快 ...
- 鼠标拖拉div宽度
先看效果 先进入页面 当鼠标停留在中间div时,鼠标变成双箭头 点击拖拉 往右边拉 往最左边拉 代码 <!DOCTYPE html> <html> <head> & ...
- 亿级Web系统搭建――单机到分布式集群 转载
当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题.为了解决这些性能压力带来问题,我们需要在Web系统架构层 ...
- 葡萄城首席架构师:前端开发与Web表格控件技术解读
讲师:Issam Elbaytam,葡萄城集团全球首席架构师(Chief Software Architect of GrapeCity Global).曾任 Data Dynamics.Inc 创始 ...
- docker中启动2个mysql实列
一.mac环境安装docker容器 在docker官网中下载docker容器,地址:https://www.docker.com/products/docker-desktop 具体安装教程及设置网络 ...
- Lucene 全文检索
基于 lucene 8 1 Lucene简介 Lucene是apache下的一个开源的全文检索引擎工具包. 1.1 全文检索(Full-text Search) 全文检索就是先分词创建索引,再执行搜索 ...
- 【洛谷】P4202 [NOI2008]奥运物流
[洛谷]P4202 [NOI2008]奥运物流 感觉有点降智 首先设环长为\(len\),很容易推导出 \[ R(1) = \frac{\sum_{i = 1}^{N} C_{i} k^{dep[i] ...
- c++ 之private /protect/ public
C++中public.protect.private的访问权限控制 访问权限 一个类的public成员变量.成员函数,可以通过类的成员函数.类的实例变量进行访问 一个类的protected成员变量.成 ...