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 ...
随机推荐
- Linear regression with one variable - Model representation
摘要: 本文是吴恩达 (Andrew Ng)老师<机器学习>课程,第二章<单变量线性回归>中第6课时<模型概述>的视频原文字幕.为本人在视频学习过程中逐字逐句记录下 ...
- 详解Arduino Uno开发板的引脚分配图及定义(重要且基础)
首先开发板实物图如下: 在本篇文章中,我们将详细介绍Arduino开发板的硬件电路部分,具体来说,就是介绍Arduino Uno开发板的引脚分配图及定义.Arduino Uno微控制器采用的是Atme ...
- 关于Angular+ngx-perfect-scrollbar自定义各大浏览器滚动条样式的解决方法
资料: http://manos.malihu.gr/jquery-custom-content-scroller/ (此项是结合Jquery使用的,在此并未采用) https://www.npmj ...
- 1-2-K Game
题目链接:https://vjudge.net/contest/330119#problem/E 题目大意可以理解为: 1.给出n个物品以及k,Alice与Bob轮流拿1个,或2个,或k个物品,Ali ...
- Design In-Memory File System
Design an in-memory file system to simulate the following functions: ls: Given a path in string form ...
- taglib block
新建文件 package com.augmentum.oes.taglib; import javax.servlet.jsp.JspException; import javax.servlet.j ...
- PHP学习之PHP的语法糖
PHP的语法糖 计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用. 常见的PHP的语法糖 echo(),print(),die(),isset(),unset(),i ...
- Swagger学习(三、配置扫描接口)
生产环境中使用,发布的时候不能使用
- [转载]PyTorch中permute的用法
[转载]PyTorch中permute的用法 来源:https://blog.csdn.net/york1996/article/details/81876886 permute(dims) 将ten ...
- PM2 部署 nodejs API项目
PM2的主要特性: 内建负载均衡(使用Node cluster 集群模块) 后台运行 0秒停机重载,我理解大概意思是维护升级的时候不需要停机. 具有Ubuntu和CentOS 的启动脚本 停止不稳定的 ...