共用表表达式(CTE)可以看成是一个临时的结果集,可以再SELECT,INSERT,UPDATE,DELETE,MARGE语句中多次引用。

一好处:使用共用表表达式可以让语句更加清晰简练。

1.可以定义递归公用表表达式(CTE)

2.当不需要将结果集作为视图被多个地方引用时,CTE可以使其更加简洁  

3.GROUP BY语句可以直接作用于子查询所得的标量列

4.可以在一个语句中多次引用公用表表达式(CTE)

二定义:公用表达式的定义非常简单,只包含三部分:

  1. 公用表表达式的名字(在WITH之后)
  2. 所涉及的列名(可选)
  3. 一个SELECT语句(紧跟AS之后)

在MSDN中的原型:

WITH expression_name [ ( column_name [,...n] ) ]
 
AS
 
( CTE_query_definition )

按照是否递归,可以将公用表(CTE)表达式分为递归公用表表达式和非递归公用表表达式.

非递归公用表表达式(CTE)

非递归公用表表达式(CTE)是查询结果仅仅一次性返回一个结果集用于外部查询调用。并不在其定义的语句中调用其自身的CTE

   非递归公用表表达式(CTE)的使用方式和视图以及子查询一致

1
2
3
4
5
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语句所示:

ith
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 CTE_Organization([SpClassifyId],[ParentClassifyId],[ClassifyName],ClassifyStatus,IsSiteInspection,IsPerformance,IsAfterPerformance,IsPmInterview,Iscbfy,IsStorage,IsRequired )
AS
(SELECT [SpClassifyId],[ParentClassifyId],[ClassifyName],ClassifyStatus,IsSiteInspection,IsPerformance,IsAfterPerformance,IsPmInterview,Iscbfy,IsStorage,IsRequired
FROM dbo.SM_SupplierClassify
WHERE [ClassifyName] like '%电梯工程%' and ClassifyStatus='Active'
UNION ALL
SELECT o.[SpClassifyId],o.[ParentClassifyId],o.[ClassifyName],o.ClassifyStatus,o.IsSiteInspection,o.IsPerformance,o.IsAfterPerformance,o.IsPmInterview,o.Iscbfy,o.IsStorage,o.IsRequired
FROM dbo.SM_SupplierClassify o INNER JOIN CTE_Organization oo ON o.[SpClassifyId]=oo.[ParentClassifyId])
SELECT distinct * FROM CTE_Organization

上述递归相关的表脚本为:

CREATE TABLE [dbo].[SM_SupplierClassify](
[SpClassifyId] [varchar](100) NOT NULL,
[ClassifyName] [nvarchar](50) NOT NULL,
[ClassifyFullName] [nvarchar](100) NULL,
[ContactPerson] [nvarchar](50) NULL,
[ContactPhone] [varchar](50) NULL,
[ParentClassifyId] [varchar](100) NULL,
[ClassifyLevel] [int] NULL,
[FullName] [nvarchar](200) NULL,
[FullId] [varchar](2000) NULL,
[ClassifyStatus] [varchar](50) NULL,
[ClassifyRemark] [nvarchar](200) NULL,
[IsSiteInspection] [bit] NULL,
[IsPerformance] [bit] NULL,
[IsAfterPerformance] [bit] NULL,
[IsPmInterview] [bit] NULL,
[SeqNo] [int] NULL,
[Isdeleted] [bit] NULL,
[CreateUserId] [int] NULL,
[CreateUserName] [nvarchar](50) NULL,
[CreateDate] [datetime] NULL,
[ModifyUserId] [int] NULL,
[ModifyUserName] [nvarchar](50) NULL,
[ModifyDate] [datetime] NULL,
[ForefatherClassifyName] [nvarchar](50) NULL,
[SupplierClassNo] [nvarchar](100) NULL,
[Iscbfy] [bit] NULL,
[IsStorage] [bit] NULL,
[IsRequired] [bit] NULL,
[IsMoreContract] [bit] NULL,
PRIMARY KEY CLUSTERED
(
[SpClassifyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO

数据为:https://files.cnblogs.com/files/chenwolong/%E6%95%B0%E6%8D%AE.zip

@陈卧龙的博客

SqlServer共用表达式(CTE)With As 处理递归查询的更多相关文章

  1. SqlServer共用表达式(CTE)With As

    共用表表达式(CTE)可以看成是一个临时的结果集,可以再SELECT,INSERT,UPDATE,DELETE,MARGE语句中多次引用. 一好处:使用共用表表达式可以让语句更加清晰简练. 1.可以定 ...

  2. SQLServer中的CTE通用表表达式

    开发人员正在研发的许多项目都涉及编写由基本的 SELECT/FROM/WHERE 类型的语句派生而来的复杂 SQL 语句.其中一种情形是需要编写在 FROM 子句内使用派生表(也称为内联视图)的 Tr ...

  3. SQLServer中的CTE(Common Table Expression)通用表表达式使用详解

    概述 我们经常会编写由基本的 SELECT/FROM/WHERE 类型的语句派生而来的复杂 SQL 语句.其中一种方案是需要编写在 FROM 子句内使用派生表(也称为内联视图)的 Transact-S ...

  4. 公用表表达式 (CTE)、递归、所有子节点、sqlserver

    指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式. 对于递归公用表达式来说,实现原理也是相同的,同样需要在语句中定义两部分 ...

  5. Sql Server 公用表达式(CTE)

    简介 对于select查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可续,在一个查询中引入另外的结果集都是通过视图而不是子查询来进行分解的,但是,视图是作为系统对象存在数据库中,那对于结果集 ...

  6. 存储过程——公用表表达式(CTE)

    目录 0. 背景说明 1. 定义及语法细节 1.1 基本定义 1.2 基本语法 1.3 多个CTE同时声明 1.4 CTE嵌套使用 2. CTE递归查询 2.1 简介 2.2 准备工作 2.3 计算每 ...

  7. SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用

    本文出处:http://www.cnblogs.com/wy123/p/5960825.html 我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等 ...

  8. 公用表表达式CTE

    公用表表达式CTE表面上和派生表非常相似,看起来只是语义上的区别.但和派生表比较起来,CTE具有几个优势:第一,如果须要在一个CTE中引用另一个CTE,不需要像派生表那样嵌套,相反,只要简单地在同一个 ...

  9. T-SQL 公用表表达式(CTE)

    公用表表达式(CTE) 在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以使用公用表表达式的方法.公用表表达式( ...

随机推荐

  1. Python 字符串内置方法笔记

    一. 大小写转换 ① capitalize() capitalize() #字符串首字母大写 >>> str0 = 'hello World' >>> str0.c ...

  2. C#中的函数(二) 有参有返回值的函数

    接上一篇 C#中的函数(-) 无参无返回值的函数 http://www.cnblogs.com/fzxiaoyi/p/8502613.html 这次研究下C#中的函数(二) 有参有返回值的函数 依然写 ...

  3. nginx 常用的中间件

    1.--with-http_stub_status_module nginx客户端状态 # 打开default.conf文件 vim /etc/nginx/conf.d/default.conf # ...

  4. CMD窗口恢复默认设置

    CMD全称Command,是Windows系统下自带的类DOS系统,在日常工作中,有时候设置会损害CMD窗口的默认,导致浏览效果不佳,这时候需要有办法恢复到默认设置.在注册表中删除以下文件夹即可:HK ...

  5. Python基础之输出格式和If判断

    格式化输出的三种方式 一.占位符 #占位符 name = 'nick' age = 19 print('my name is %s my age is %s' % (name, age)) age = ...

  6. RHCE试题解析

    环境准备 yum-config-manager --add-repo=ADDREPO vim /etc/yum.conf gpgcheck=0(1=on,0=off)   增加指定repo源,关闭签名 ...

  7. hibernate关联关系 (多对多)

    hibernate的多对多 hibernate可以直接映射多对多关联关系(看作两个一对多  多对多关系注意事项 一定要定义一个主控方 多对多删除 主控方直接删除 被控方先通过主控方解除多对多关系,再删 ...

  8. axios发送自定义请求头的跨域解决

    前端发送来的axios请求信息 this.$axios.request({  url:'http://127.0.0.1:8001/pay/shoppingcar/',  method:'post', ...

  9. PATB1009说反话

    这里有一点需要注意的就是,PAT里面是禁用gets函数的,所以要换成一个替代函数 那就是下面这个: //这个是定义一个字符串数组 char str[90]; //需要被替代的函数 gets(str) ...

  10. Springboot之自定义配置

    SpringBoot自定义配置 springboot在这里就不过多介绍了,大家都应该了解springboot零配置文件,所以配置信息都装配在属性文件(properties.yml.yaml)中,有时我 ...