Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 

PracticalSQLDba

I have total of 11 years of IT experience with Application development, Database Development and Database Administration. I have worked with different version of SQL server from 7.0 to 2008.Started my carrier as VB ,VC++ and database developer in a banking sector for implementing their core banking solution. Currently working as Database Administrator with wide knowledge in performance tuning, high availability solution, troubleshooting and server monitoring. This blog is my humble attempt to share my knowledge and what I learned from my day to day work.

SQL Server: How Recursive Common Table Expression (CTE) Works ?

Last Friday evening, I forced to look into a procedure which is using Recursive Common Table (CTE) . The procedure was not returning the result.I was not very comfortable with the recursive CTE as I am not able to visualize the execution of recursive CTE. After struggling for an hour , we managed to fix the issue. Then I thought it will be good to learn how the recursive CTE works. In this post let us see how recursive CTE works.

First of all let us create a table called Employee table using the below script.

CREATE TABLE Employee
(Employee_id             INT PRIMARY KEY,
EmployeeName          VARCHAR(100),
Manager_id                 INT
)
Let us populate the sample data.
INSERT INTO Employee VALUES (1,'A',NULL)
INSERT INTO Employee VALUES (2,'A_B',1)
INSERT INTO Employee VALUES (3,'A_C',1)
INSERT INTO Employee VALUES (4,'A_D',1)

INSERT INTO Employee VALUES (5,'B_B',2)
INSERT INTO Employee VALUES (6,'B_C',2)

INSERT INTO Employee VALUES (7,'C_B',3)
INSERT INTO Employee VALUES (8,'C_C',3)

INSERT INTO Employee VALUES (9,'BB_B',5)
INSERT INTO Employee  VALUES (10,'BB_C',5)

INSERT INTO Employee VALUES (11,'BC_B',6)
INSERT INTO Employee VALUES (12,'BC_C',6)

INSERT INTO Employee VALUES (13,'BBB_B',9)
INSERT INTO Employee VALUES (14,'BBC_B',10)  

I have used separate insert statement for better readability.

Here Manager_id is a foreign key referring to Employee_id. Let us assume that we need to generate an employee reports with Employee_id,Employee Name ,Manager_id,Manager Name and hierarchical position (level) of employee in the organization. This can be implemented very easily using recursive CTE which introduced in SQL server 2005.Below script will give the result.

;WITH DirectReports(Manager_ID, ManagerName,Employee_ID, EmployeeName ,EmployeeLevel)
AS (
  
--Select the root or parent records
    
SELECT 
         Manager_ID,
         CAST('' AS VARCHAR(100))AS ManagerName
         Employee_ID
         EmployeeName,
         0 AS EmployeeLevel
    FROM Employee
    WHERE Manager_ID IS NULL

    
UNION ALL
   
 --Recursive part :Select the child
 
SELECT 
     e.Manager_ID,
     m.EmployeeName AS ManagerName
     e.Employee_ID
     e.EmployeeName,
     EmployeeLevel + 1
 FROM Employee e
        INNER JOIN DirectReports d
        ON e.Manager_ID = d.Employee_ID
        INNER  JOIN employee m ON e.manager_ID = m.employee_id
)
SELECT * FROM DirectReports ;

Let us see how we can write the same with out CTE, which will help us to visualize the recursive CTE.

DECLARE @DirectReports AS TABLE
  
(Manager_ID INT,
  
ManagerName VARCHAR(100),
  
Employee_ID INT,
  
EmployeeName VARCHAR(100) ,
  
EmployeeLevel INT)--Selecting the 0th level (who do not have manager) employee

INSERT INTO @DirectReports
    
SELECT Manager_ID,
    
CAST('' AS VARCHAR(100))AS ManagerName,
    
Employee_ID, EmployeeName ,
    
0 AS EmployeeLevel
    FROM Employee
    WHERE Manager_ID IS NULL 

DECLARE @Recursion INT =0
WHILE(@@ROWCOUNT>0)BEGIN
      
       SET
@Recursion =@Recursion +1
       INSERT INTO @DirectReports
      
SELECT
      
e.Manager_ID,
      
m.EmployeeName AS ManagerName,
      
e.Employee_ID,
      
e.EmployeeName ,
      
@Recursion
      
FROM Employee e
        INNER JOIN @DirectReports d
        ON e.Manager_ID = d.Employee_ID
        INNER  JOIN employee m ON e.manager_ID = m.employee_id
        WHERE d.EmployeeLevel=@Recursion -1 --to select only the last execution result
  
END
SELECT
* FROM @DirectReports
  

Hope this will help us to write/troubleshoot the recursive CTE in much comfortable way.

If you liked this post, do like my page on FaceBook

Comments

Leave a comment on the original post [www.practicalsqldba.com, opens in a new window]

Loading comments...