本文来自:http://blog.csdn.net/songjie521/article/details/3321030

通用表表达式(CTEs)是SQL Server 2005的一项新功能。它们类似于alias(如在SELECT T1.* FROM MyTable T1中),不过功能更为强大。本质上,CTE是一个临时结果集,它仅仅存在于它发生的语句中。您可以在SELECT、INSERT、DELETE、 UPDATE或CTEATE VIEW语句中建立一个CTE。CTE类似于派生表,但拥有几项优点。

CTE的优点

与派生表不同,CTE能够引用自己本身。如果您不必存储视图,您可以用一个CTE来代替它。在一个语句中,您还可以多次引用CTE。应用CTE,您可以通过一个派生栏对结果进行分组。
您可以将查询区域分割成可读的“块”,然后用这些块建立一个复杂的查询。执行递归查询是CTE最重要也是最强大的功能。

建立CTE

CTE通过关键字WITH建立,其模板为:

WITH CTE_name[ (column_name [,...n] ) ]
AS
( CTE_query_specification )

以下为多个示例的使用:

USE Northwind
--结果列别名
WITH c AS 
(
SELECT YEAR(orderdate) AS orderyear,customerid
FROM Orders
)

SELECT orderyear,COUNT(DISTINCT customerid)AS numCusts FROM c GROUP BY orderyear
--使用参数
DECLARE @empid AS INT 
SET @empid=3
WITH c AS 
(
SELECT YEAR(orderdate) AS orderyear,customerid
FROM Orders
WHERE employeeid=@empid
)
SELECT orderyear,COUNT(DISTINCT customerid)AS numCusts FROM c GROUP BY orderyear


--多CTE.不同于派生表,CTE不能被直接嵌套.即,你不能在一个CTE内定义另一个CTE.但是,你可以用一个WITH语句定义多个CTE.
WITH c1 AS 
(
SELECT YEAR(orderdate) AS orderyear,customerid
FROM Orders
),
c2 AS 
(
SELECT orderyear,COUNT(DISTINCT customerid)AS numcusts FROM c1 GROUP BY orderyear
)

SELECT orderyear,numcusts FROM c2 WHERE numcusts>70


--多引用: 相对于派生表,CTE的一个优势是你可以在外部查询中多次引用同一个CTE名称.
WITH YearlyCount AS 
(
SELECT YEAR(orderdate) AS orderyear,COUNT(DISTINCT customerid)AS numcusts FROM orders GROUP BY YEAR(orderdate)
)

SELECT cur.orderyear,cur.numcusts,prv.orderyear,prv.numcusts,Cur.numcusts-prv.numcusts
FROM yearlyCount Cur LEFT JOIN YearlyCount Prv
ON cur.Orderyear=Prv.orderyear+1

--修改数据.可能通过CTE修改数据
--建立测试表
IF OBJECT_ID('CustomersDups')IS NOT NULL
DROP TABLE CustomersDups

WITH CrossCustomers AS 
(
SELECT 1 AS c,c1.* FROM customers AS c1,customers AS c2
)
SELECT ROW_NUMBER()OVER(ORDER BY c)AS keycol,CustomerID,CompanyName,ContactName,ContactTitle,Address,City,
Region,PostalCode,Country,Phone,Fax    
INTO customerdups 
FROM CrossCustomers 

SELECT * FROM customerdups

CREATE UNIQUE INDEX index_idx_customerid_keycol
ON customerdups (customerid,keycol)

--以下删除重复的数据. 
WITH JustDups AS 
(
--此查询语句不能得到对应的重复数据SELECT * FROM customerdups AS c1 WHERE keycol<(SELECT MAX(keycol) FROM customerdups AS c2 WHERE c2.customerid=c1.customerid)
    select * from customerdups as c1 where keycol in (select max(keycol) from customerdups as c2 group by col1.col2...)
)
DELETE FROM justdups

--容器对象,CTE可以用于诸如视图或内联UDF这样的容器中.这种能力允许实现封装.要熟练掌握.
--视图
CREATE VIEW dbo.vYearCnt
AS 
WITH YearCnt AS 
(
SELECT YEAR(orderdate) AS orderyear,COUNT(DISTINCT customerid)AS numCusts FROM Orders GROUP BY YEAR(orderdate)
)
SELECT * FROM YearCnt
GO 

SELECT * FROM vYearCnt

--UDF,可传递一个输入参数
CREATE FUNCTION dbo.ufn_EmpYearCnt(@EmpID AS INT) RETURNS TABLE   
AS   
RETURN   
  WITH EmpYearCnt AS   
  (  
    SELECT YEAR(OrderDate) AS OrderYear,  
     COUNT(DISTINCT CustomerID) AS NumCusts  
     FROM dbo.Orders  
     WHERE EmployeeID=@EmpID  
     GROUP BY YEAR(OrderDate)  
  )  
  SELECT * FROM EmpYearCnt;

SELECT * FROM ufn_EmpYearCnt(2)

--递归CTE,是SQL 2005中最重要的TSQL增强之一。通过纯基于集合的查询实现了递归查询。
/*下面用一个示例来描述递归CTE。给一个参数,要求你根据由EmployeeID和ReportsTo属性维护的层次关系,返回输入员工和该员工所有级别的下属。要为每个员工返回的属性包括:employeeID、ReportsTo、FirstName和LastName
*/
--先创建覆盖索引,以忧化该任务。
CREATE UNIQUE INDEX idx_mgr_emp_ifname_ilname
ON employee(reportsTo,EmployeeID)include(FirstName,LastName)
--该索引允许通过使用一次查找和一次局部扫描提取每位经理的直接下属。注意索引中包含列FirstName和LastName以实现覆盖。下面是递归CTE。
WITH EmpsCTE AS 
(
SELECT employeeID,ReportsTo,Firstname,LastName
FROM Employees
WHERE employeeID=5
UNION ALL
SELECT Emp.EmployeeID,Emp.ReportsTo,Emp.FirstName,Emp.LastName
FROM EmpsCTE AS Mgr JOIN employees Emp
ON emp.ReportsTo=mgr.employeeid
)
--查看员工5和它的下属
SELECT * FROM EmpsCTE

/*递归CTE最少包含两个查询(也称为成员)。CTE主体中的第一个查询被称为定位点成员(Anchor Member)。定位点成员只是一个返回有效表的查询,用于递归的基础或定位点。在以上的示例中,定位点成员直接返回输入根员工(员工5)所在的行。CTE主体中的第二个查询递归成员(Recursive Member)。使该查询成为递归成员的是对CTE名称(EmpsCTE)的递归引用。注意该引用不同于在外部查询中对CTE名称的引用。外部查询中的引用得到由该CTE返回的结果集,不包含递归。而内部引用是在该CTE的结果表确定之前使用的,它是触发递归的关键元素。*/

DROP INDEX employees.idx_mgr_emp_ifname_ilname

限制:不能在一个语句中建立两个CTE。

使用公用表表达式(CTE)的更多相关文章

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

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

  2. 公用表表达式CTE

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

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

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

  4. 详解公用表表达式(CTE)

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

  5. T-SQL查询进阶--详解公用表表达式(CTE)

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

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

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

  7. SQL Server进阶(六)表表达式--派生表、公用表表达式(CTE)、视图和内联表值函数

    概述 表表达式是一种命名的查询表达式,代表一个有效地关系表.可以像其他表一样,在数据处理中使用表表达式. SQL Server支持四种类型的表表达式:派生表,公用表表达式,视图和内联表值函数. 为什么 ...

  8. 公用表表达式(CTE)

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

  9. SQL Server 公用表表达式(CTE)实现递归

    公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...

  10. mysql8 公用表表达式CTE的使用

    公用表表达式CTE就是命名的临时结果集,作用范围是当前语句. 说白点你可以理解成一个可以复用的子查询,当然跟子查询还是有点区别的,CTE可以引用其他CTE,但子查询不能引用其他子查询. 一.cte的语 ...

随机推荐

  1. <% %> 、 <%= %> 、<%# %> 的区别

    1,<% %>用来绑定后台代码    中间一般放函数或者方法,典型的asp程序写法. 在前台页面可以写后台代码                 相当于开辟了C#空间,可以写C#代码 2,& ...

  2. string字母排序,

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. iOS-网络编程(一)HTTP协议

    一. 网络编程基础 在移动互联网时代,几乎所有应用都需要用到网络,只有通过网络跟外界进行数据交互.数据更新,应用才能保持新鲜.活力.一个好的移动网络应用不仅要有良好的UI和良好的用户体验也要具备实时更 ...

  4. SpringMVC(二)——流程控制

    SpringMVC主要就是用来做流程控制的,这篇博客总结一下如何在流程控制添加Interceptor(拦截器),如何将进行流程Mapping映射解析,如何编写Controller(控制器). 一,首先 ...

  5. Monkey Tradition(中国剩余定理)

    Monkey Tradition Time Limit: 2000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Submi ...

  6. C++11里面的Lambda表达式

    Lambda Expressions in C++ C++中的Lambda表达式 In Visual C++, a lambda expression—referred to as a lambda— ...

  7. DIV + CSS 盒子模型

    盒子模型有两种,分别是 IE 盒子模型和标准 W3C 盒子模型.他们对盒子模型的解释各不相同, 先来看看我们熟悉的标准盒子模型: 图片看不清楚?请点击这里查看原图(大图). 从上图可以看到标准 W3C ...

  8. gcc基本用法

    GCC基本用法 GCC最基本的用法是: gcc [option] filenames option:编译器所需要的编译选项 filenames:要编译的文件名 gcc编译流程 都以 hello.c 为 ...

  9. OD调试3--reverseMe

    OD调试3:reverseMe.exe(reverse就是逆向的意思) 运行效果图: 1关于寄存器 寄存器就好比是CPU身上的口袋,方便CPU随时从里边拿出需要的东西来使用.今天的程序中涉及到九个寄存 ...

  10. Linux中Firefox——Firebug插件安装及使用

    Firebug的安装方法即打开方式同httpfox Firebug使用指南: Firebug可以随时编辑页面:在HTML标签中,点击窗口上方的"inspect"命令,然后再选择页面 ...