T-SQL之公用表表达式(CTE)
T-SQL查詢處理詳解 (續) T-SQL邏輯處理之表運算符 廢話就不多說了,公用表表達式(Common Table Expressions), 是SQL SERVER支持的一種類型的表表達式。 CTE的語法如下: WITH <cte_name> [(<target_col_list>)] AS ( <定義CTE的內部查詢> ) <對CTE進行外部查詢>; CTE的語法,從WITH開始,首先在括號里定義CTE內部查詢,然后在外部查詢引用CTE的名稱。 對CTE的內部查詢表達式,有如下規則: 1.查詢必須是一個有效的表; 2.所有的列必須要有名稱; 3.所有的列名必須唯一; 4.不允許使用order by(除非同時指定了top,原因很簡單,因為order by之后,返回的是游標,但是如果同時指定了top,則order by可以當作是top的排序方式)。 下面是一個CTE的例子。 use Northwind;
go
with EmployeeYearOrder as
(
select (e.FirstName+N' '+e.LastName) as employeename,year(o.orderdate) as theyear,COUNT(o.OrderID) ordernum from dbo.Orders o
inner join dbo.Employees e on o.EmployeeID = e.EmployeeID
group by e.FirstName+N' '+e.LastName,year(o.orderdate)
)
select * from EmployeeYearOrder cur
left join EmployeeYearOrder pre on cur.theyear = pre.theyear+1
上邊的例子是多引用的CTE,利用CTE定義了每年的雇員的訂單的數目,在外部查詢中,通過兩次引用EmployeeYearOrder ,一個代表當前年份,一個代表上一年。
如果使用派生表的話,代碼是如下組織的:
use Northwind;go
select * from
(
select (e.FirstName+N' '+e.LastName) as employeename,year(o.orderdate) as theyear,COUNT(o.OrderID) ordernum from dbo.Orders o
inner join dbo.Employees e on o.EmployeeID = e.EmployeeID
group by e.FirstName+N' '+e.LastName,year(o.orderdate)
)as cur
left join
(
select (e.FirstName+N' '+e.LastName) as employeename,year(o.orderdate) as theyear,COUNT(o.OrderID) ordernum from dbo.Orders o
inner join dbo.Employees e on o.EmployeeID = e.EmployeeID
group by e.FirstName+N' '+e.LastName,year(o.orderdate)
) as pre on cur.theyear = pre.theyear+1;
注意上邊的查詢,核心查詢的部分重復了兩次。查詢越復雜,引用次數越多,基于CTE的解決方案越有優勢。當然從性能上來講,這兩種寫法,經過查詢優化器分析后,最終都得到同樣的執行計劃。
還有多CTE的情況。CTE不允許直接嵌套,但是可以用同一個WITH定義多個CTE,從而得到和嵌套派生表相同的效果,但是卻沒有嵌套派生表那么復雜。
看下邊的查詢:
多CTE的解決方案,返回的是每個雇員每一年處理的訂單的數目 with c1 as(
select YEAR(orderdate) as theyear,(e.FirstName+N' '+e.LastName) as employeename,OrderID from dbo.Orders as o
inner join dbo.Employees e on o.EmployeeID = e.EmployeeID
),
c2 as
(
select theyear,employeename,COUNT(OrderID) ordernum from c1
group by theyear,employeename
)
select employeename,theyear,ordernum from c2;
就是一個多CTE的例子,看起來比多層嵌套的派生表要直觀。
CTE最大的用處,我覺得還是遞歸查詢。
還是給出一個例子。
WITH Emps AS(
SELECT empid, mgrid, firstname, lastname
FROM HR.Employees
WHERE empid = 5
UNION ALL
SELECT Emp.empid, Emp.mgrid, Emp.firstname, Emp.lastname
FROM Emps AS Mgr
JOIN HR.Employees AS Emp
ON Emp.mgrid = Mgr.empid
)
SELECT * FROM Emps;
這段查詢將返回每位經理的直接下屬。
如上查詢所示,遞歸的CTE,必須包含至少兩個查詢。第一個查詢被成為定位點成員,它只是一個返回有效表的查詢,作為遞歸的基礎或定位點。而第二個查詢則成為遞歸成員,是該查詢成為遞歸成員的是對CTE名稱的遞歸引用。如果擔心循環的發生,則可以指定option(maxrecursion n)來限制遞歸成員的調用次數。關于CTE的更多應用和深入理解,有機會再深入去講解。
對于T-SQL公用表表達式,就講到這里,有什么問題,還請大家指出,一起探討。
參考文獻:《Microsoft SQL Server 2008 技術內幕:T-SQL查詢》
轉載于:https://www.cnblogs.com/JimmyGe/archive/2011/03/12/1981998.html
總結
以上是生活随笔為你收集整理的T-SQL之公用表表达式(CTE)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZZ:WSS 扩展文件夹的属性--如何给
- 下一篇: Eclipse安装Alibaba Clo