使用公用表表达式(CTE)

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

使用公用表表达式(CTE)WITH CTE_name[ (column_name [,...n] ) ]
使用公用表表达式(CTE)AS
使用公用表表达式(CTE)( CTE_query_specification )

以下为多个示例的使用:

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

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

上一篇:ado中dispose和close的区别,摘自网络


下一篇:Java集合框架