Почему следует использовать общие табличные выражения? - PullRequest
1 голос
/ 02 июля 2010

Я только что прочитал эту ссылку 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 ]

3 голосов
/ 02 июля 2010

Что, если вы хотите показать уровня менеджера людям со всеми своими подчиненными?(Например, все сотрудники уровня 2 со всеми, кто находится под ними, - либо в виде прямого отчета, либо в виде отчета в прямой отчет, либо в виде отчета в прямой отчет в прямой отчет и т. Д.)

Это было бы довольно просто сделать с помощью CTE.Не так просто без этой рекурсии.

CTE также может сделать запросы намного более читабельными, вместо того, чтобы включать один и тот же подзапрос несколько раз в один оператор SQL.Такое дублированное обслуживание также может быть проблемой, когда вы меняете один подзапрос, но забыли изменить другой.Это также повышает производительность во многих местах, потому что SQL Server может оценивать и сохранять результаты CTE один раз.

0 голосов
/ 18 июня 2014

Другим примером хорошего использования 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...