博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL 递归查询,意淫CTE递归的执行步骤
阅读量:5740 次
发布时间:2019-06-18

本文共 2847 字,大约阅读时间需要 9 分钟。

 

今天用到了sql的递归查询。递归查询是CTE语句with xx as(....)实现的。

假如表Category数据如下。

我们想查找机枪这个子分类极其层次关系(通过子节点,查询所有层级节点)。以下是查询语句

 

WITH tt AS (SELECT CategoryId,Name,Parent,0 level  FROM dbo.Category WHERE CategoryId=15  --定位点成员UNION ALLSELECT 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

 

转载于:https://www.cnblogs.com/MLGB/p/7921579.html

你可能感兴趣的文章
Silverlight 2.5D RPG游戏“.NET技术”技巧与特效处理:(十二)魔法系统
查看>>
PHP 命令行模式实战之cli+mysql 模拟队列批量发送邮件(在Linux环境下PHP 异步执行脚本发送事件通知消息实际案例)...
查看>>
pyjamas build AJAX apps in Python (like Google did for Java)
查看>>
LAMP环境搭建1-mysql5.5
查看>>
centos5.9使用RPM包搭建lamp平台
查看>>
Javascript String类的属性及方法
查看>>
[LeetCode] Merge Intervals
查看>>
SharePoint 读取 Site Columns 的数据并绑定到DropdownList
查看>>
使用 axios 详解
查看>>
IPA提交APPStore问题记录(一)
查看>>
Ubuntu 14.04 vsftp refusing to run with writable root inside chroot问题解决方法
查看>>
Intellij IDEA远程调试tomcat
查看>>
hadoop的学习论坛
查看>>
Struts2 学习小结
查看>>
烂泥:wordpress迁移到docker
查看>>
.扒渣机的性能及优势 
查看>>
Linux下磁盘保留空间的调整,解决df看到的空间和实际磁盘大小不一致的问题
查看>>
RSA 生成公钥、私钥对
查看>>
测试工具综合
查看>>
asp.net中调用COM组件发布IIS时常见错误 80070005解决方案
查看>>