SQL 研究- Common Table Expression

Common Table Expression,简称 CTE,是SQL Server中的三种保存临时结果的方法之一。另外两种是临时表和View,当然你也可以说View并不保存数据,从这一点上来将, CTE更像View一些。

当你的查询需要从一个源表中统计出结果,基于这个结果再做进一步的统计,如此3次以上的话,你必然会用到View或者临时表,现在你也可以考虑用CTE了。

 

CTE的语法相当的简单, 如下:

With CTE的名字 AS

(

子查询

)

Select * from CTE的名字

 

CTE可以实现很多不可思议的功能,巧妙之处在于CTE可以出现自己的子查询里。让我们从简单的问题开始。

 

先假设一个需求,贵公司的员工表存放着员工号,员工直接经理的员工号,以及员工的Title,现在需要查询出各个员工所在的层次,从0开始。

 

于是你看到这样的表:

create table Employee
(
MgrId int,
EmpId int,
Title nvarchar(256)
)

表中的内容如下:

NULL1CEO
12VP
23Dev Manager
24QA Manager
15Sales Manager
330Developer
331Developer
440Tester
441Tester

 

你期望得到这样的结果:

NULL1CEO0
12VP1
15SalesManager1
23DevManager2
24QAManager2
440Tester3
441Tester3
330Developer3
331Developer3

 

最后一列为所得到的层次数字。

 

使用如下的SQL能得到上面的效果:

 

With DirectReports as
(
select MgrId, EmpId, Title, 0 as [Level] from Employee where MgrId is null

union all

select a.MgrId, a.EmpId, a.Title, [Level]+1 as [Level]
from Employee a join  DirectReports b on a.MgrId=b.EmpId
)
select * from DirectReports

 

为什么这个语句能够沿着CEO往下一层一层走下去,最终找到所有的员工呢?

显然要理解这一SQL必须理解包含在 as只有括号里的嵌套查询。它由两个查询结合而成:

select ..

Union All

Select..

 

这两个Select语句在CTE中有特殊的意义。

 

第一个Select子句被称为 锚点 语句,它返回的结果跟普通的SQL没有区别,在这里返回MgrID为null的员工。可见没有Manager是件多么美好的事情。

 

第二个子句就没那么普通了,它被称为 递归 语句,请注意到在from后面, Employee和DirectReport进行了链接操作。您一定会问,DirectReport的定义还没完成,这个名字代表什么结果呢?答案是它不只是代表了一个结果,实际上代表了一系列的结果。换句话说,在DirectReport这个名字下,包含着DirectReport0,DirectReport1,DirectReport2...这些较小的集合。

DirectReport0 是Employee和 锚点 结合的产物;

DirectReport1 是Employee和 DirectReport0 结合的产物;

依次类推, DirectReport n是Employee和DirectReport n-1结合的产物;

当DirectReport_n为空的时候,这个过程就结束了。

 

最后 锚点和DirectReport0,DirectReport1... 的并集就是DirectReport的内容。

 

作为一个程序员,每次看到递归的程序,必然会想到无限递归这个错误。为了避免了在开发阶段,无限递归导致数据库的崩溃,SQL Server提供了一个QueryHint, MaxRecursion,可以控制递归的最大层数,如果超过这个数字而仍为结束,则视为代码错误,强制退出。以本文所用的SQL为例,可以如下使用MaxRecursion。

With DirectReports as
(
select MgrId, EmpId, Title, 0 as [Level] from Employee where MgrId is null

union all

select a.MgrId, a.EmpId, a.Title, [Level]+1 as [Level]
from Employee a join  DirectReports b on a.MgrId=b.EmpId
)
select * from DirectReports

Option(MaxRecursion 10) 

 

正如我之前所说, CTE能完成更多的工作,让我们以后进一步挖掘。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值