SqlServer共用表达式(CTE)With As
共用表表达式(CTE)可以看成是一个临时的结果集,可以再SELECT,INSERT,UPDATE,DELETE,MARGE语句中多次引用。
一好处:使用共用表表达式可以让语句更加清晰简练。
1.可以定义递归公用表表达式(CTE)
2.当不需要将结果集作为视图被多个地方引用时,CTE可以使其更加简洁
3.GROUP BY语句可以直接作用于子查询所得的标量列
4.可以在一个语句中多次引用公用表表达式(CTE)
二定义:公用表达式的定义非常简单,只包含三部分:
- 公用表表达式的名字(在WITH之后)
- 所涉及的列名(可选)
- 一个SELECT语句(紧跟AS之后)
在MSDN中的原型:
WITH expression_name [ ( column_name [,...n] ) ] AS ( CTE_query_definition )
按照是否递归,可以将公用表(CTE)表达式分为递归公用表表达式和非递归公用表表达式.
非递归公用表表达式(CTE)
非递归公用表表达式(CTE)是查询结果仅仅一次性返回一个结果集用于外部查询调用。并不在其定义的语句中调用其自身的CTE
WITH cte_Test AS
(
SELECT * FROM dbo.SysOrganization
)
SELECT * FROM cte_Test
公用表表达式的好处之一是可以在接下来一条语句中多次引用:

只能接下来一条使用:

由于CTE只能在接下来一条语句中使用,因此,当需要接下来的一条语句中引用多个CTE时,可以定义多个,中间用逗号分隔:

递归公用表表达式(CTE)
递归公用表表达式很像派生表(Derived Tables ),指的是在CTE内的语句中调用其自身的CTE.与派生表不同的是,CTE可以在一次定义多次进行派生递归.对于递归的概念,是指一个函数或是过程直接或者间接的调用其自身,递归的简单概念图如下:
对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分:
- 基本语句
- 递归语句
在SQL这两部分通过UNION ALL连接结果集进行返回:

当然,越强大的力量,就需要被约束.如果使用不当的话,递归CTE可能会出现无限递归。从而大量消耗SQL Server的服务器资源.因此,SQL Server提供了OPTION选项,可以设定最大的递归次数:
还是上面那个语句,限制了递归次数:

2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示:
with
cte1 as
(
select * from table1 where name like 'abc%'
),
cte2 as
(
select * from table2 where id > 20
),
cte3 as
(
select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id
3. 不能在 CTE_query_definition 中使用以下子句:
(1)COMPUTE 或 COMPUTE BY (2)ORDER BY(除非指定了 TOP 子句) (3)INTO (4)带有查询提示的 OPTION 子句 (5)FOR XML (6)FOR BROWSE
4.如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:
declare @s nvarchar(3)
set @s = 'C%'
; -- 必须加分号
with
t_tree as
(
select CountryRegionCode from person.CountryRegion where Name like @s
)
select * from person.StateProvince where CountryRegionCode in (select * from t_tree)
. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:
declare @s nvarchar(3)
set @s = 'C%'
; -- 必须加分号
with
t_tree as
(
select CountryRegionCode from person.CountryRegion where Name like @s
)
select * from person.StateProvince where CountryRegionCode in (select * from t_tree)
比较复杂的例子:
;WITH v_targetdetail(ID,ParentID,TargetID,TargetName,
TargetGroupID,ConversionValue,ToTargetID,IsCalculated,IsLeaf,
IDFullPath,IsDisplay,Unit,TargetLevelID,TargetType) AS (
-- DECLARE @accountGroupID NVARCHAR(38)='ac11e71148564dd3a28d07142883ab99'
SELECT p.ID
--父级ID
,p.ParentID
--实际指标ID
,ISNULL(p.TargetID,p.ID) TargetID
--名称
,p.Name TargetName
--指标组ID
,p.GroupID TargetGroupID
--转换值
,p.ConversionValue
--目标指标ID
,p.ToTargetID
--是否计算
,p.IsCalculated
--是否是叶子
,p.IsLeaf
--ID值
,CAST(p.ID AS NVARCHAR(MAX)) IDFullPath
--是否显示
,p.IsDisplay
-- 单位
,p.Unit
--级别
,p.LevelID
--指标类型
,p.TargetType
--指标组表
FROM ToBusinessTargetGroupDetail2(NOLOCK) p
--父级ID为空 是否上报
WHERE (p.ParentID IS NULL OR p.IsReported=0) AND p.GroupID=@accountGroupID--'ac11e71148564dd3a28d07142883ab99'-- --全部关联
UNION ALL
--递归语句
SELECT
p.ID
,p.ParentID
,ISNULL(p.TargetID,p.ID) TargetID
,p.Name TargetName
,p1.TargetGroupID
,p.ConversionValue
,p.ToTargetID
,p.IsCalculated
,p.IsLeaf
,CAST(p1.IDFullPath+'.'+p.ID AS NVARCHAR(MAX))IDFullPath
,p.IsDisplay
,p.Unit
,p.LevelID
,p.TargetType FROM ToBusinessTargetGroupDetail2(NOLOCK) p
--第一次查询的表 p1为 第一次汇总的值 p为指标详细表 得到的指表组ID==原表的指标组ID
INNER JOIN v_targetdetail p1 ON p1.ID=p.ParentID AND p1.TargetGroupID=p.GroupID
--已经上报的
WHERE p.IsReported=1
) --第二次
,v_taregetsummaryref(TargetDetailID,pTargetID,pTargetName,sTargetID,
sTargetName,ConversionValue,pToTargetID,sIsLeaf,
TargetLevelID,Unit,TargetType,TargetOrderID) AS (
SELECT p.ID
,p.TargetID pTargetID
,p.TargetName pTargetName
,p1.TargetID sTargetID
,p1.TargetName sTargetName
,p.ConversionValue
--,p1.ConversionValue
,p.ToTargetID
,p1.IsLeaf
,p.TargetLevelID
,p.Unit
,p.TargetType
,NULL
--第一次
FROM v_targetdetail p
INNER JOIN v_targetdetail p1 ON p1.TargetGroupID=p.TargetGroupID AND p1.IDFullPath LIKE p.IDFullPath+'%'
WHERE p.IsDisplay=1
) --插入到临时表
INSERT INTO #t_target(TargetDetailID,pTargetID,pTargetName,sTargetID,sTargetName,ConversionValue,pToTargetID,TargetOrderID,TargetLevelID,Unit,TargetType,isleaf)
--从最终的表里面查询结果出来
SELECT TargetDetailID,pTargetID,pTargetName,sTargetID,sTargetName,
ConversionValue,pToTargetID,TargetOrderID,TargetLevelID,
--第二次递归的表
Unit,TargetType, sIsLeaf FROM v_taregetsummaryref
UNION ALL
SELECT p1.TargetDetailID
,p1.pTargetID
,p1.pTargetName
,p2.ID sTargetID
,p2.Name sTargetName
,p1.ConversionValue
,p1.pToTargetID
,p1.TargetOrderID
,p1.TargetLevelID+p2.LevelID
,p1.Unit
,10
,p2.IsLeaf
--科目表
FROM ToFinanceAccount(NOLOCK) p
--最终的结构表 最终结果表ID ==科目表的ID 最终结果表 是叶子结点的数据
INNER JOIN v_taregetsummaryref p1 WITH(NOLOCK) ON p1.sTargetID=p.ID AND p1.sIsLeaf=1
--科目表 名称全路径 和没有删除的数据
INNER JOIN dbo.ToFinanceAccount p2 WITH(NOLOCK) ON p2.FullPath LIKE p.FullPath+'\%' AND ISNULL(p2.IsDelete,0)=0
--没有删除的数据
WHERE ISNULL(p.IsDelete,0)=0
--科目表中不是叶节点的数据
AND p.IsLeaf!=1
SqlServer共用表达式(CTE)With As的更多相关文章
- SqlServer共用表达式(CTE)With As 处理递归查询
共用表表达式(CTE)可以看成是一个临时的结果集,可以再SELECT,INSERT,UPDATE,DELETE,MARGE语句中多次引用. 一好处:使用共用表表达式可以让语句更加清晰简练. 1.可以定 ...
- SQLServer中的CTE通用表表达式
开发人员正在研发的许多项目都涉及编写由基本的 SELECT/FROM/WHERE 类型的语句派生而来的复杂 SQL 语句.其中一种情形是需要编写在 FROM 子句内使用派生表(也称为内联视图)的 Tr ...
- 公用表表达式 (CTE)、递归、所有子节点、sqlserver
指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式. 对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分 ...
- SQLServer中的CTE(Common Table Expression)通用表表达式使用详解
概述 我们经常会编写由基本的 SELECT/FROM/WHERE 类型的语句派生而来的复杂 SQL 语句.其中一种方案是需要编写在 FROM 子句内使用派生表(也称为内联视图)的 Transact-S ...
- SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用
本文出处:http://www.cnblogs.com/wy123/p/5960825.html 我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等 ...
- 公用表表达式CTE
公用表表达式CTE表面上和派生表非常相似,看起来只是语义上的区别.但和派生表比较起来,CTE具有几个优势:第一,如果须要在一个CTE中引用另一个CTE,不需要像派生表那样嵌套,相反,只要简单地在同一个 ...
- T-SQL 公用表表达式(CTE)
公用表表达式(CTE) 在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以使用公用表表达式的方法.公用表表达式( ...
- 详解公用表表达式(CTE)
简介 对于SELECT查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可读,在一个查询中引用另外的结果集都是通过视图而不是子查询来进行分解的.但是,视图是作为系统对象存在数据库中,那对于结果集 ...
- T-SQL查询进阶--详解公用表表达式(CTE)
简介 对于SELECT查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可读,在一个查询中引用另外的结果集都是通过视图而不是子查询来进行分解的. 但是,视图是作为系统对象存在数据库中,那对于结果 ...
随机推荐
- delphi制作登陆窗体
delphi登陆窗体的制作,就我知道的,可以有两种方法,一种是在工程文件中实现登陆窗体的动态调用,另一种就是在主窗体的OnCreate事件中动态创建登陆窗体,两种方法都需要将主窗体设置为Auto-cr ...
- hdu 4747 Mex (2013 ACM/ICPC Asia Regional Hangzhou Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 思路: 比赛打得太菜了,不想写....线段树莽一下 实现代码: #include<iost ...
- Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)
这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...
- [0,x)的随机数
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #in ...
- GROUP BY和 HAVING 及 统计函数 执行顺序等
[我理解:where是对最外层结果进行条件筛选,而having是对分组时分组中的数据进行 组内条件筛选,注意:只能进行筛选,不能进行统计或计算,所有统计或计算都要放在最外层的select 后面,无论是 ...
- Javascript面向
一.前言 面向对象:专注于由哪一个对象来解决这个问题,编程特点是出现了一个类,从类中拿到对象,由这个对象去解决具体问题. 对于调用者来说,面向过程需要调用者自己去实现各种函数.而面向对象, ...
- node.js原生后台进阶(二)
上一章讲到怎么样用原生node.js来获取GET.POST(urlencoded,formData)的参数,这一次我们更进一步,讲一下以下的点: 1.压缩(zlib) 2.流(stream) 3.路由 ...
- python中的无参装饰器和有参装饰器
python中的无参装饰器和有参装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 装饰器特点: 1>.开放封闭原则,即对扩展是开放的,对修改时封闭的: 2>.装饰器 ...
- win7下PLSQL Developer提示“ORA-12154: TNS:无法解析指定的连接标识符”
解决方法:卸载掉重新安装,注意安装的目录的文件夹不要有特殊的符号,例如64位系统的的安装目录会到Program Files (x86),这时候就会出现"ORA-12154: TNS:无法解析 ...