2010-07-02 61 views
1

我剛剛看了這個鏈接http://msdn.microsoft.com/en-us/library/ms186243.aspx爲什麼要使用公用表表達式?

這裏是代碼來創建表並插入數據: -

-- Create an Employee table. 
CREATE TABLE dbo.MyEmployees 
(
    EmployeeID smallint NOT NULL, 
    FirstName nvarchar(30) NOT NULL, 
    LastName nvarchar(40) NOT NULL, 
    Title nvarchar(50) NOT NULL, 
    DeptID smallint NOT NULL, 
    ManagerID int NULL, 
CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC) 
); 
-- Populate the table with values. 
INSERT INTO dbo.MyEmployees VALUES 
(1, N'Ken', N'S�nchez', N'Chief Executive Officer',16,NULL) 
,(273, N'Brian', N'Welcker', N'Vice President of Sales',3,1) 
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',3,273) 
,(275, N'Michael', N'Blythe', N'Sales Representative',3,274) 
,(276, N'Linda', N'Mitchell', N'Sales Representative',3,274) 
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',3,273) 
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',3,285) 
,(16, N'David',N'Bradley', N'Marketing Manager', 4, 273) 
,(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16); 

他們給這個CTE: -

WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level) 
AS 
(
-- Anchor member definition 
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, 
     0 AS Level 
    FROM dbo.MyEmployees AS e 
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh 
     ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL 
    WHERE ManagerID IS NULL 
    UNION ALL 
-- Recursive member definition 
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, 
     Level + 1 
    FROM dbo.MyEmployees AS e 
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh 
     ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL 
    INNER JOIN DirectReports AS d 
     ON e.ManagerID = d.EmployeeID 
) 
-- Statement that executes the CTE 
SELECT ManagerID, EmployeeID, Title, DeptID, Level 
FROM DirectReports 
INNER JOIN HumanResources.Department AS dp 
    ON DirectReports.DeptID = dp.DepartmentID 
WHERE dp.GroupName = N'Sales and Marketing' OR Level = 0; 
GO 

,並得到這樣的輸出: -

ManagerID EmployeeID Title       Level 
--------- ---------- ----------------------------- ------ 
NULL  1   Chief Executive Officer  0 
1   273  Vice President of Sales  1 
273  16   Marketing Manager    2 
273  274  North American Sales Manager 2 
273  285  Pacific Sales Manager   2 
16  23   Marketing Specialist   3 
274  275  Sales Representative   3 
274  276  Sales Representative   3 
285  286  Sales Representative   3 

嗯,我寫爲除了關卡號之外,還有幾乎相同的結果: -

Select e.ManagerId, 
     m.FirstName as [Manager Name], 
     e.EmployeeId, 
     e.FirstName as [Employee Name], 
     e.Title 
from dbo.MyEmployees e 
    LEFT JOIN dbo.MyEmployees m 
     On e.ManagerId = m.EmployeeId; 

CTE只打印關卡號的目的是什麼?有人可以給我一些具體的例子,說明爲什麼需要CTE?

感謝提前:)

+0

該示例在遞歸方案中提供了CTE用法。嘗試這種方式,而不使用CTE,你會明白爲什麼它很有用。 – 2010-07-02 16:18:13

回答

3

,如果你想要的東西,以顯示經理級別的人與所有下屬的? (例如,所有「二級」員工與其下的任何人員 - 無論是作爲直接報告還是作爲直接報告的報告,或作爲直接報告直接報告的報告等)

這對CTE來說很簡單。沒有這種遞歸就不那麼容易了。

CTE還可以使查詢更具可讀性,而不必在單個SQL語句中多次包含相同的子查詢。當您更改一個子查詢但忘記更改另一個子查詢時,重複維護也可能成爲問題。這也是許多地方的性能提升,因爲SQL Server可以評估和保存一次CTE結果。

+0

謝謝。在沒有CTE的情況下,我不得不每次都發射一個查詢嗎?就像有人點擊經理(在鏈接上)以顯示他下面的下屬一樣。然後,對於該ManagerId顯示它是下屬,即我認爲可能是我們可以在C#中創建一個遞歸函數,而不是遞歸查詢(CTE),並不斷調用我們的存儲過程來檢索它的下屬。我知道這將會非常緩慢,但如果沒有CTE,我們可以做到。對? – TCM 2010-07-02 16:37:32

+1

當然,你可以帶走幾乎任何結構,並且還可以繞過它。 CTE可以通過一個語句向您的所有下屬致電給DB。如果你想的話,你可以刪除所有的SQL,只是通過一個平面文件迭代所有的數據訪問。我不會建議,但:) – 2010-07-03 15:56:44

0

另一個很好的CTE使用的例子是刪除重複項,這是我目前工作中的主要用途。代碼使用示例:

WITH cte 
     AS (SELECT * , 
        ROW_NUMBER() OVER (PARTITION BY PlantId, Plant, 
             DeliveryDate, RouteId, CustomerId, 
             ProductId, Quantity ORDER BY PlantId, Plant, DeliveryDate, RouteId, CustomerId, ProductId, Quantity) AS Rowid 
      FROM  dbo.RAW_ORDERS_WEST 
     ) 
DELETE FROM CTE 
WHERE Rowid > 1