Common Table Expressions (CTE) w T-SQL

CTE w T-SQL można porównać do tymczasowej tabeli. Prawdziwa siła CTE jednak tkwi w możliwości rekurencyjnego przechodzenia przez węzły. Ogólna zasada tworzenia wygląda następująco:

WITH expression_name [ ( column_name [,...n] ) ]

AS

( CTE_query_definition ) 

exoression_name stanowi nazwę obiektu CTE. Następnie listujemy wszystkie kolumny, które będą występować w CTE. Za słowem kluczowym AS występuje selekcja danych – tak jak w zwykłych widoku. Stwórzmy więc obiekt CTE:


WITH FirstCte (FirstName,LastName)
AS
(
    SELECT FirstName,LastName from Address where ID_PERSON in (1,2,3);
)

Korzystanie z CTE niczym nie różni się od wykonywania zapytań na zwykłej tabeli:

select FirstName FROM FirstCte order BY LastName desc;

CTE służy jednak głównie do rekurencyjnych zapytań. Klasycznym przykładem jest struktura pracowników w firmie – każdy ma przełożonego itp. Dla testów stwórzmy tabelę, która zawiera 3 kolumny (ID_EMPLOYEE,ID_MANAGAER,TITLE). Definicja CTE składa się zawsze z przynajmniej dwóch zapytań  rozdzielonych klauzulą UNION ALL. Pierwsze zapytania to tzw. kotwica (anchor) – generuje pierwszy wiersz drzewa. Druga z kolei wykorzystuje zdefiniowaną kotwicę oraz odwołuje się do samego obiekt CTE, tym samym powodując rekurencję. Podejrzewam, że w tej chwili jest to kompletnie niezrozumiałe więc przejdźmy od razu do przykładu:

WITH EmployeeStructureCte (ManagerID, EmployeeID, Title, Level)
AS
(
    SELECT e.ManagerID, e.EmployeeID, e.Title, 
        0 AS Level
    FROM Employees as e WHERE ManagerID IS NULL --kotwica
    UNION ALL
    SELECT e.ManagerID, e.EmployeeID, e.Title,
        Level + 1
    FROM Employees as e    
    INNER JOIN EmployeeStructureCte AS cte
        ON e.ManagerID = cte.EmployeeID;
)

Prześledźmy po kolei działanie powyższej struktury (która może wydawać się dziwna na pierwszy rzut oka). Najpierw wywoływana jest kotwica, która zwróci:

ManagerID EmployeeID Title Level
NULL 1 Szef 0

Nic nadzwyczajnego – prosta zapytanie SELECT. Drugie zapytanie zwróci np. taki wiersz (lub grupę wierszy):

ManagerID EmployeeID Title Level
1 2 Zastępca szefa 1

Następny krok to już czysta rekurencja- wykorzystujemy właśnie zwrócony wiersz i szukamy podwładnych np.:

ManagerID EmployeeID Title Level
2 3 nie wazne 2
2 4 nie wazne 2

Rekurencja zakończy się w momencie gdy będzie “brakowało” podwładnych:) Wtedy nastąpi połączenie wszystkich wierszy za pomocą UNION ALL. Wygenerowany CTE można wykorzystać np. aby zwrócić wyłącznie pracowników danego szczebla:

SELECT * FROM EmployeeStructureCte where Level = 3

Leave a Reply

Your email address will not be published.