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 ...
随机推荐
- 义隆单片机学习笔记之(一) 硬件框架&资源下载
参考网址: 点击链接或右键链接地址 (台湾义隆官网)http://www.emc.com.tw/chs/tech_8bit.asp (EM78P153K官方资料)http://www.emc.com. ...
- WCF中事务处理
一.引言 今天来介绍下WCF对事务的支持. 二.WCF事务详解 2.1 事务概念与属性 首先,大家在学习数据库的时候就已经接触到事务这个概念了.所谓事务,它是一个操作序列,这些操作要么都执行,要么都不 ...
- sql语句 两表关联查询计算数量
select sum(a1.`num`) from `order_orderlistrow` as a1 INNER JOIN `order_orderlist` as a2 on a1.`ord ...
- ajax head带参数两次请求
ajax请求head里带数据 客户端先发一次option看看能不能登录,然后再发一次post
- [Agc028B]Removing Blocks_排列组合
Removing Blocks 题目链接:https://atcoder.jp/contests/agc028/tasks/agc028_b 数据范围:略. 题解: 这种问题的第一步很套路,就是对于每 ...
- Linux Centos下软件的安装与卸载方法
转载于: http://blog.csdn.net/zolalad/article/details/11368879 Linux下软件的安装与卸载 第一章 linux下安装软件,如何知道软件安 ...
- thinkphp5.1路由设置小计
route下定义路由路径,如果是这种情况 'product'=>'home/product/index',//产品信息首页 'product/list'=>'home/product/li ...
- 【规律】Growing Rectangular Spiral
Growing Rectangular Spiral 题目描述 A growing rectangular spiral is a connected sequence of straightline ...
- java对象序列化并存储到文件中
● 如何将一个Java对象序列化到文件里 使用输入输出流,,一个是ObjectOutputStream 对象,ObjectOutputStream 负责向指定的流中写入序列化的对象.当从文件中读取序列 ...
- table html
<html><head><title>demo-110101</title><style type="text/css"> ...