码迷,mamicode.com
首页 > 其他好文 > 详细

使用公用表表达式(CTE)

时间:2014-10-27 09:14:46      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   ar   使用   strong   

本文来自: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建立,其模板为:

bubuko.com,布布扣WITH CTE_name[ (column_name [,...n] ) ]
bubuko.com,布布扣AS
bubuko.com,布布扣( CTE_query_specification )


以下为多个示例的使用:

bubuko.com,布布扣USE Northwind
bubuko.com,布布扣--结果列别名
bubuko.com,布布扣WITH c AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT YEAR(orderdate) AS orderyear,customerid
bubuko.com,布布扣FROM Orders
bubuko.com,布布扣)
bubuko.com,布布扣
bubuko.com,布布扣SELECT orderyear,COUNT(DISTINCT customerid)AS numCusts FROM c GROUP BY orderyear
bubuko.com,布布扣--使用参数
bubuko.com,布布扣DECLARE @empid AS INT 
bubuko.com,布布扣SET @empid=3
bubuko.com,布布扣WITH c AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT YEAR(orderdate) AS orderyear,customerid
bubuko.com,布布扣FROM Orders
bubuko.com,布布扣WHERE employeeid=@empid
bubuko.com,布布扣)
bubuko.com,布布扣SELECT orderyear,COUNT(DISTINCT customerid)AS numCusts FROM c GROUP BY orderyear
bubuko.com,布布扣
bubuko.com,布布扣
bubuko.com,布布扣--多CTE.不同于派生表,CTE不能被直接嵌套.即,你不能在一个CTE内定义另一个CTE.但是,你可以用一个WITH语句定义多个CTE.
bubuko.com,布布扣WITH c1 AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT YEAR(orderdate) AS orderyear,customerid
bubuko.com,布布扣FROM Orders
bubuko.com,布布扣),
bubuko.com,布布扣c2 AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT orderyear,COUNT(DISTINCT customerid)AS numcusts FROM c1 GROUP BY orderyear
bubuko.com,布布扣)
bubuko.com,布布扣
bubuko.com,布布扣SELECT orderyear,numcusts FROM c2 WHERE numcusts>70
bubuko.com,布布扣
bubuko.com,布布扣
bubuko.com,布布扣--多引用: 相对于派生表,CTE的一个优势是你可以在外部查询中多次引用同一个CTE名称.
bubuko.com,布布扣WITH YearlyCount AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT YEAR(orderdate) AS orderyear,COUNT(DISTINCT customerid)AS numcusts FROM orders GROUP BY YEAR(orderdate)
bubuko.com,布布扣)
bubuko.com,布布扣
bubuko.com,布布扣SELECT cur.orderyear,cur.numcusts,prv.orderyear,prv.numcusts,Cur.numcusts-prv.numcusts
bubuko.com,布布扣FROM yearlyCount Cur LEFT JOIN YearlyCount Prv
bubuko.com,布布扣ON cur.Orderyear=Prv.orderyear+1
bubuko.com,布布扣
bubuko.com,布布扣--修改数据.可能通过CTE修改数据
bubuko.com,布布扣--建立测试表
bubuko.com,布布扣IF OBJECT_ID(‘CustomersDups‘)IS NOT NULL
bubuko.com,布布扣DROP TABLE CustomersDups
bubuko.com,布布扣
bubuko.com,布布扣WITH CrossCustomers AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT 1 AS c,c1.* FROM customers AS c1,customers AS c2
bubuko.com,布布扣)
bubuko.com,布布扣SELECT ROW_NUMBER()OVER(ORDER BY c)AS keycol,CustomerID,CompanyName,ContactName,ContactTitle,Address,City,
bubuko.com,布布扣Region,PostalCode,Country,Phone,Fax    
bubuko.com,布布扣INTO customerdups 
bubuko.com,布布扣FROM CrossCustomers 
bubuko.com,布布扣
bubuko.com,布布扣SELECT * FROM customerdups
bubuko.com,布布扣
bubuko.com,布布扣CREATE UNIQUE INDEX index_idx_customerid_keycol
bubuko.com,布布扣ON customerdups (customerid,keycol)
bubuko.com,布布扣
bubuko.com,布布扣--以下删除重复的数据. 
bubuko.com,布布扣WITH JustDups AS 
bubuko.com,布布扣(
bubuko.com,布布扣--此查询语句不能得到对应的重复数据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...)
bubuko.com,布布扣)
bubuko.com,布布扣DELETE FROM justdups
bubuko.com,布布扣
bubuko.com,布布扣--容器对象,CTE可以用于诸如视图或内联UDF这样的容器中.这种能力允许实现封装.要熟练掌握.
bubuko.com,布布扣--视图
bubuko.com,布布扣CREATE VIEW dbo.vYearCnt
bubuko.com,布布扣AS 
bubuko.com,布布扣WITH YearCnt AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT YEAR(orderdate) AS orderyear,COUNT(DISTINCT customerid)AS numCusts FROM Orders GROUP BY YEAR(orderdate)
bubuko.com,布布扣)
bubuko.com,布布扣SELECT * FROM YearCnt
bubuko.com,布布扣GO 
bubuko.com,布布扣
bubuko.com,布布扣SELECT * FROM vYearCnt
bubuko.com,布布扣
bubuko.com,布布扣--UDF,可传递一个输入参数
bubuko.com,布布扣CREATE FUNCTION dbo.ufn_EmpYearCnt(@EmpID AS INT) RETURNS TABLE   
bubuko.com,布布扣AS   
bubuko.com,布布扣RETURN   
bubuko.com,布布扣  WITH EmpYearCnt AS   
bubuko.com,布布扣  (  
bubuko.com,布布扣    SELECT YEAR(OrderDate) AS OrderYear,  
bubuko.com,布布扣     COUNT(DISTINCT CustomerID) AS NumCusts  
bubuko.com,布布扣     FROM dbo.Orders  
bubuko.com,布布扣     WHERE EmployeeID=@EmpID  
bubuko.com,布布扣     GROUP BY YEAR(OrderDate)  
bubuko.com,布布扣  )  
bubuko.com,布布扣  SELECT * FROM EmpYearCnt;
bubuko.com,布布扣
bubuko.com,布布扣SELECT * FROM ufn_EmpYearCnt(2)
bubuko.com,布布扣
bubuko.com,布布扣--递归CTE,是SQL 2005中最重要的TSQL增强之一。通过纯基于集合的查询实现了递归查询。
bubuko.com,布布扣/*下面用一个示例来描述递归CTE。给一个参数,要求你根据由EmployeeID和ReportsTo属性维护的层次关系,返回输入员工和该员工所有级别的下属。要为每个员工返回的属性包括:employeeID、ReportsTo、FirstName和LastName
bubuko.com,布布扣*/
bubuko.com,布布扣--先创建覆盖索引,以忧化该任务。
bubuko.com,布布扣CREATE UNIQUE INDEX idx_mgr_emp_ifname_ilname
bubuko.com,布布扣ON employee(reportsTo,EmployeeID)include(FirstName,LastName)
bubuko.com,布布扣--该索引允许通过使用一次查找和一次局部扫描提取每位经理的直接下属。注意索引中包含列FirstName和LastName以实现覆盖。下面是递归CTE。
bubuko.com,布布扣WITH EmpsCTE AS 
bubuko.com,布布扣(
bubuko.com,布布扣SELECT employeeID,ReportsTo,Firstname,LastName
bubuko.com,布布扣FROM Employees
bubuko.com,布布扣WHERE employeeID=5
bubuko.com,布布扣UNION ALL
bubuko.com,布布扣SELECT Emp.EmployeeID,Emp.ReportsTo,Emp.FirstName,Emp.LastName
bubuko.com,布布扣FROM EmpsCTE AS Mgr JOIN employees Emp
bubuko.com,布布扣ON emp.ReportsTo=mgr.employeeid
bubuko.com,布布扣)
bubuko.com,布布扣--查看员工5和它的下属
bubuko.com,布布扣SELECT * FROM EmpsCTE
bubuko.com,布布扣
bubuko.com,布布扣/*递归CTE最少包含两个查询(也称为成员)。CTE主体中的第一个查询被称为定位点成员(Anchor Member)。定位点成员只是一个返回有效表的查询,用于递归的基础或定位点。在以上的示例中,定位点成员直接返回输入根员工(员工5)所在的行。CTE主体中的第二个查询递归成员(Recursive Member)。使该查询成为递归成员的是对CTE名称(EmpsCTE)的递归引用。注意该引用不同于在外部查询中对CTE名称的引用。外部查询中的引用得到由该CTE返回的结果集,不包含递归。而内部引用是在该CTE的结果表确定之前使用的,它是触发递归的关键元素。*/
bubuko.com,布布扣
bubuko.com,布布扣DROP INDEX employees.idx_mgr_emp_ifname_ilname

 

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

使用公用表表达式(CTE)

标签:style   blog   http   color   io   os   ar   使用   strong   

原文地址:http://www.cnblogs.com/zhouyunbaosujina/p/4053392.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!