CTE (Common Table Expression)
Overview
- It is called Common Table Expression, introduced in SQL 2005
- It is kind of temporary result set with a scope of single DML operation (INSERT / UPDATE / DELETE)
- It will be stored in memory
- It will last only till the duration of the query
- It can be self referenced which is the best usage of CTE
- It is really useful in terms of recursion and deleting duplicate records
Advantages
- Improved readability
- Easy maintenance of complex queries
- Can be defined in views also
- Really works well for recursion and deleting duplicate records
Disadvantages
- Above statement should be enclosed with ;
- Cannot handle millions of records, #TEMP table will be a replacement in that scenario
Basic Syntax
WITH cte_name (optional column list)
AS
(
Cte_query
)
statement that uses the above CTE
Recursive Syntax
WITH cte_name (optional column list)
AS
(
Cte_query --Anchor Member
Union All
Cte_query -- Recursive Member
)
statement that uses the above CTE
Different Usages
- Basic use to replace Table variable or #TEMP table
-- Creating Table
CREATE TABLE Employee (EmployeeID INT, Name VARCHAR(50), ManagerID INT, DOB DATETIME)
-- Inserting Records
INSERT INTO Employee
VALUES
(1,'Kamlesh',NULL, '1960-01-01')
,(2,'Pratibha',1, '1960-05-01')
,(3,'Maulik',1 ,'1980-01-01')
,(4,'Nisarg',1,'1983-01-01')
,(5,'Dipa',3,'1982-01-01')
,(6,'Swara',5,'2008-01-01')
,(7,'Megha',4,'1986-01-01');
-- Query
WITH StartsWithM
AS
(
SELECT Name FROM Employee WHERE Name LIKE 'M%'
)
SELECT * FROM StartsWithM
- Using CTE for recurssion
-- Query (Find out complete hierarchy of Swara)
WITH Hierarchy (EmployeeID, Name, ManagerID, Level)
AS
(
-- Anchor Member Definition
SELECT EmployeeID, Name, ManagerID, 1 Level
FROM Employee
WHERE EmployeeID = 6
UNION ALL
-- Recursive Member Definition
SELECT E.EmployeeID, E.Name, E.ManagerID, Level + 1
FROM Employee E
INNER JOIN Hierarchy H ON H.ManagerID = E.EmployeeID
)
SELECT
H.EmployeeID
, H.Name EmployeeName
, Level
, H.ManagerID
, ISNULL(E.Name,'<--No Manager-->') ManagerName
FROM Hierarchy H
LEFT JOIN Employee E ON H.ManagerID = E.EmployeeID
- CTE within CTE / CTE with multiple reference
/* Find out the employees with their managers who born prior to 1985
We can write without using CTE in a much simpler way but this is just an example of using one CTE inside other CTE */
WITH PriorTo1985
AS
(
SELECT *
FROM Employee
WHERE DOB < '1985-01-01'
),
Manager
AS
(
SELECT E.Name, ISNULL(M.Name,'No Manager') ManagerMame
FROM PriorTo1985 P
INNER JOIN Employee E
ON P.EmployeeID = E.EmployeeID
LEFT JOIN Employee M
ON E.ManagerID = M.EmployeeID
)
SELECT * FROM Manager
- CTE within MAXRECURSION Hint
Maximum recursion is 100, if we want to go beyond that then we have to use MAXRECURSION Hint
If we don’t use it, by default it will take 100
We can give number from 0 to 32767
DECLARE @startDate DATETIME,
@endDate DATETIME
SET @startDate = '11/10/2011'
SET @endDate = '03/25/2012';
WITH CTE AS
(
SELECT YEAR(@startDate) AS 'yr',
MONTH(@startDate) AS 'mm',
DATENAME(mm, @startDate) AS 'mon',
DATEPART(d,@startDate) AS 'dd',
@startDate 'new_date'
UNION ALL
SELECT
YEAR(new_date) AS 'yr',
MONTH(new_date) AS 'mm',
DATENAME(mm, new_date) AS 'mon',
DATEPART(d,@startDate) AS 'dd',
DATEADD(d,1,new_date) 'new_date'
FROM CTE
WHERE new_date < @endDate
)
SELECT yr AS 'Year', mon AS 'Month', count(dd) AS 'Days'
FROM CTE
GROUP BY mon, yr, mm
ORDER BY yr, mm
OPTION (MAXRECURSION 1000)
No comments:
Post a Comment