Sunday, September 25, 2016

Common Table Expressions in SQL Server

This is an interesting topic that I came across while working with Microsoft SQL server and it is the concept of common table expressions.


Common Table Expressions generally referred to as CTE is a key concept in SQL Server. It is a temporary named resultset that can be referenced within a DML operation like Insert/Delete/Update/Merge. Suppose we have to do a join of table and then join the above resultset with another table. There are 3 ways of doing it .One is to create a table with join of 2 tables and then in another sql query join the above created table with that of the second table. It is a feasible solution .But creating lot of standard tables increases the complexity and result in confusion. Also if the intermediate result is of no use later then there is no point in doing so. The second is creating a complex SQL query with many subquerys which will do the functionality. Yes, it is also a viable solution.But from a third persons perspective this may sound weird since he may not be able to understand the functionality easily.Hence we finally arrive at the third solution which is the CTE


There are 2 types of CTE supported by SQL server and they are recursive CTE s and non recursive CTE s.Lets first look at non recursive CTE s


Non Recursive CTE s :

           Non Recursive CTE s are temporary resultset that reference other tables and not itself. Lets look at the syntax for this
 
with t1(c1,c2)
as
    (
       select m1,sum(m2)
       from t 2
       group by m1
    )
      select c1,a1,sum(c2)
      from t3 join t1
      on t3.a1=t1.c1
      group by c1,a1;


This may sound confusing. Let us look into the query in detail. I have created a CTE which is table t1 with columns c1 and c2. this means that the query by which the CTE is created should return 2 columns of the same datatype . I am using the columns m1 and their aggregation which is the sum from another table into the CTE which is the t1 .so T1 has 2 columns which is the m1 column of t2 and the aggregated value of m2 .Now after creating the CTE am joining the CTE table that is t1 with another table t3 and pulling the values form both the tables. Now this would have become more clear


Lets look at it further with the help of employees, departments and locations tables, If I want to find the location of an employee and their sum of salaries in each location based on each department I need to join the employees and departments table and then join it with the locations table. Lets use a CTE for that now


with temp_dep (emp_id,dept_id,emp_name,sal)
as
   (
     select emp_id, dept_id,emp_name,sum(salary) as sal
     from employees
    group by emp_id,emp_name,dept_id,
  )
     select location,emp_name,sal
     from locations l join temp_dep d
     on l.dept_id=d.dept_id

This would give me the location and their sum(salary).This made the understanding of the query more easy since we have two definitions and by looking closer we know what does each query intended to do.


Recursive CTE :


                   Recursive CTE s are those that reference itself .Like finding a hierarchy we might create a GTE and refer that in the table creation itself. We might have learned self join where in we join employees with the same table employees and use first tables employee id = second tables manager id condition. The same logic applies here .Lets see an example


WITH
  cteReports (EmpID, FirstName, LastName, MgrID, EmpLevel)
  AS
  (
    SELECT EmployeeID, FirstName, LastName, ManagerID, 1
    FROM Employees
    WHERE ManagerID IS NULL
    UNION ALL
    SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID,
      r.EmpLevel + 1
    FROM Employees e
      INNER JOIN cteReports r
        ON e.ManagerID = r.EmpID
  )
SELECT
  FirstName + ' ' + LastName AS FullName,
  EmpLevel,
  (SELECT FirstName + ' ' + LastName FROM Employees
    WHERE EmployeeID = cteReports.MgrID) AS Manager
FROM cteReports
ORDER BY EmpLevel, MgrID


Here the first section mentioned in blue is the anchor member and the second section highlighted in violet is the recursive section. The recursive section as we can see refer the same CTE table that we created and that section can only refer a CTE .Both the Anchor member and the recursive members are joined by Union/Union all/Intersect or by any set operators. All the Anchor members must precede the recursive members and both must return the same number of columns with matching datatype. This may sound little complex,but when it comes TSQL it is very useful for doing any operations on the tables like select,insert,update,delete and so on.           
              







No comments:

Post a Comment