2011-03-03 134 views
11

公共表表達式的優勢,我們在寫SQL CTE類似下面一個什麼是SQL Server

WITH yourCTE AS 
(
SELECT .... FROM :... WHERE..... 
) SELECT * FROM yourCTE 

會有什麼優勢,把SQL與塊。我認爲,如果我們把複雜的SQL與塊,然後我們可以寫像SQL SELECT * FROM yourCTE。就好像我正在訪問視圖一樣。 在性能方面使用CTE有哪些額外優勢。請討論。謝謝

回答

3

This MSDN article描述它是最好的。底線是,如果您已經從視圖中選擇數據,則不必將其包裝在CTE中,然後從CTE中選擇。我不認爲CTE和觀點之間有很大差異(性能明智)。至少不是以我的經驗(我一直在處理一些複雜的數據庫結構,最近有很多記錄)。然而,CTE對於遞歸選擇是理想的。

不過,另一件事是,如果您要在查詢中多次選擇相同的連接數據子集並且沒有爲其定義視圖,則CTE可能會有所幫助。我認爲如果你只是爲了一個單一的查詢而加入數據,然後把它封裝在一個CTE中,那就太過分了。查詢路徑仍然會得到緩存,即使你不使用CTE ...

+0

你說CTE是遞歸選擇的理想選擇。你想說什麼遞歸選擇。請讓我明白,什麼是由CTE遞歸選擇。 – Thomas 2011-03-03 06:58:01

+0

再次,MSDN通過關於使用CTE的遞歸查詢的詳細文章來解決:http://msdn.microsoft.com/zh-cn/library/ms186243.aspx。還可以查看marc的答案,其中提供了一個非常簡短的(但容易理解的)遞歸查詢的解釋。 – FarligOpptreden 2011-03-03 07:07:15

12

有許多情況下,其中一個CTE可真有用:

  • 遞歸查詢,像走了一個層次樹 - 這是非常棘手和繁瑣無CTE(見here for a sample of a recursive CTE)要使用的排名功能ROW_NUMBER()RANK(),一個

  • 隨時隨地等等(請參閱here for info on ranking functions

  • 一般情況下,您需要根據某些標準先選擇幾行/列,然後對其進行操作。更新表,刪除重複等

一個情況下,我經常使用的CTE被刪除所有,但最近的一組給定的數據的行,例如如果您有客戶,並且與訂單的關係爲1:n,並且您想要刪除除最近訂單(基於OrderDate)之外的所有訂單,那麼對於每個客戶而言,在沒有CTE的情況下在SQL中執行此操作會非常繁瑣。

的CTE和排序功能,這是一件輕而易舉的事:

;WITH CustomerOrders AS 
(
    SELECT 
     c.CustomerID, o.OrderID, 
     ROW_NUMBER() OVER(PARTITION BY c.CustomerID ORDER BY o.OrderDate DESC) AS 'RowN' 
    FROM 
     dbo.Customer c 
    INNER JOIN 
     dbo.Orders o ON o.CustomerID = c.CustomerID 
) 
DELETE FROM 
    dbo.Orders 
FROM 
    CustomerOrders co 
WHERE 
    dbo.Orders.OrderID = co.OrderID 
    AND co.RowN > 1 

有了這個,你創建一個「在線視圖」,通過CustomerID分區(例如,每個客戶得到從1開始rownumbers),以便通過OrderDate DESC(最新訂單優先)。對於每個客戶,最新的,最近的訂單有RowN = 1,所以你可以很容易地刪除所有其他的行,你已經做了你想做的事情 - 與CTE一塊蛋糕 - 沒有它的雜亂代碼....

+0

當你簡單地說:'從CTE中刪除,如你的例子中那樣,RDBMS如何知道它應從哪個表中刪除? – 2011-03-03 09:12:29

+0

@Andriy M:更新了我的查詢 - 這應該讓它更加明顯。 – 2011-03-03 09:37:59

+0

確實非常明顯,謝謝。:) – 2011-03-03 10:54:30

-2

今天晚上好。今天我們要了解的是Common table表達式,它是SQL Server 2005中引入的一個新功能,也可以在更高版本中使用。公用表表達式: - 公用表表達式可以被定義爲一個臨時結果集,換句話說,它可以被SQL Server中的視圖替代。公用表表達式僅在定義語句的批處理中有效,並且不能在其他會話中使用。

語法聲明CTE(公用表表達式)的: -

with [Name of CTE] 
as 
(
Body of common table expression 
) 

讓我們的示例: -

CREATE TABLE Employee([EID] [int] IDENTITY(10,5) NOT NULL,[Name] [varchar](50) NULL) 

insert into Employee(Name) values('Neeraj') 
insert into Employee(Name) values('dheeraj') 
insert into Employee(Name) values('shayam') 
insert into Employee(Name) values('vikas') 
insert into Employee(Name) values('raj') 

CREATE TABLE DEPT(EID INT,DEPTNAME VARCHAR(100)) 
insert into dept values(10,'IT') 
insert into dept values(15,'Finance') 
insert into dept values(20,'Admin') 
insert into dept values(25,'HR') 
insert into dept values(10,'Payroll') 

我已經創建了兩個表僱員和DEPT和在每個表中插入的5行。現在我想加入這些表格並創建一個臨時結果集以進一步使用它。

With CTE_Example(EID,Name,DeptName) 
as 
(
select Employee.EID,Name,DeptName from Employee 
inner join DEPT on Employee.EID =DEPT.EID 
) 
select * from CTE_Example 

讓我們逐句逐句理解。

定義CTE我們寫「與」條款,那麼我們給一個名字表表達式,在這裏我給名爲「CTE_Example」

然後我們寫「爲」,並在兩個括號包含我們的代碼(---),我們可以在括號內加入多個表格。

在最後一行中,我使用了「Select * from CTE_Example」,我們在最後一行代碼中引用了Common表達式,所以我們可以說它就像一個視圖,我們正在定義和使用在單個批次中查看並且CTE不會作爲永久性對象存儲在數據庫中。但它表現得像一個觀點。我們可以在CTE上執行刪除和更新語句,這將直接影響正在CTE中使用的引用表。讓我們舉一個例子來理解這個事實。

With CTE_Example(EID,DeptName) 
as 
(
select EID,DeptName from DEPT 
) 
delete from CTE_Example where EID=10 and DeptName ='Payroll' 

在上面的語句,我們正在刪除從CTE_Example行,它會刪除從在熱膨脹係數所使用的參考表「DEPT」的數據。

我希望這篇文章對您有所幫助,只要您覺得合適,您就可以使用CTE。

+0

我知道這篇文章有點舊,但是因爲人們已經低估了這個答案,所以我想我會添加一個爲什麼我這麼做的理由。 OP正在詢問CTE將提供什麼優勢。這篇文章向我們展示瞭如何做一個CTE,而不是爲什麼它應該被使用。 – Semperfi89 2017-01-19 14:17:13

0
  1. 進行遞歸查詢。
  2. 在定義名爲給定的臨時區域中虛擬地保存查詢輸出。
  3. 無需保存元數據。
  4. 當需要對某些查詢輸出執行更多操作時很有用。
  5. 查詢輸出保留,直到查詢正在運行
  6. 保留臨時數據以進一步處理的最佳使用。
  7. 允許比單個查詢更多的分組選項。
  8. 允許從一個複雜的查詢獲得標量數據