为什么要使用Common Table Expressions?

时间:2010-07-02 16:15:12

标签: sql-server-2008

我刚看了这个链接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?

提前致谢:)

2 个答案:

答案 0 :(得分:3)

如果您希望向所有下属显示经理级人员,该怎么办? (例如,所有“二级”员工与其下的任何人 - 作为直接报告或作为直接报告的报告,或作为直接报告直接报告的报告等)。

这对CTE来说相当简单。没有这种递归就不那么容易了。

CTE还可以使查询更具可读性,而不必在单个SQL语句中多次包含相同的子查询。当您更改一个子查询但忘记更改另一个子查询时,重复的维护也可能是一个问题。这也是许多地方的性能提升,因为SQL Server可以评估并保存一次CTE结果。

答案 1 :(得分: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