Cte in SQL
Cte in SQL
SQL
COMMON TABLE EXPRESSION - CTE:
Consider a scenario:
Suppose, you’re organizing a birthday party.
• Step 01: You first make a guest list of everyone you want to invite.
• Step 02: Then, you use that list to plan things like seating arrangements or food orders.
The guest list isn’t a permanent document—it’s just a temporary tool to help you plan your party
efficiently.
In SQL, a CTE is like that temporary guest list. It helps you prepare data that you can use later in
the same query.
Formal Definition:
A CTE (Common Table Expression) in SQL is like a temporary table or a shortcut that you can
create and use within the same query.
It helps you organize and simplify your SQL code, especially when working with complex queries.
Syntax:
WITH CTE_Name AS (
-- Your query goes here
SELECT column1, column2, ...
FROM table_name
WHERE condition
)
-- Main query referencing the CTE
SELECT *
FROM CTE_Name
WHERE another_condition;
Example 01:
Suppose,
• You have data stored in table ‘Employees’.
• You have to analyze employees who have a salary above the department's average salary.
CTE Breakdown:
1. DepartmentAverage CTE:
• Computes the average salary for each department.
• Result of DepartmentAverage:
DepartmentID AvgSalary
101 75000
102 82500
103 62500
1. Main Query:
• Joins the Employees table with the DepartmentAverage CTE.
• Filters employees earning more than their department's average salary.
Explanation:
• Bob (Department 101) earns 80,000, which is above the average of 75,000 for his
department.
• Charlie (Department 102) earns 90,000, which is above the average of 82,500 for his
department.
TYPES OF CTEs in SQL:
In SQL, Common Table Expressions (CTEs) can be broadly categorized into the following types
based on their usage and characteristics:
Syntax:
WITH CTEName AS (
UNION ALL
We want to list the employees in a hierarchical order starting from top-level managers.
WITH EmployeeHierarchy AS (
UNION ALL
Explanation:
1. Base Case:
• Starts with the CEO (ManagerID IS NULL).
• Includes their EmployeeID, Name, ManagerID, and sets Level = 0.
2. Recursive Step:
• For each employee in the current level, finds their subordinates by matching
EmployeeID with the ManagerID in the Employees table.
• Increments the level by 1 for subordinates.
3. Termination:
• Stops automatically when no more employees are found for the next level.
• The base case selects John as the top-level manager (Level 0).
• The recursive case selects employees Alice and Bob (Level 1) under John.
• Further recursion finds employees under Alice and Bob at Level 2.
Syntax:
WITH CTE_Name AS (
SELECT <columns>
FROM <table_name>
WHERE <conditions>
)
SELECT <columns>
FROM CTE_Name;
Explanation:
• The CTE named TotalSales calculates the total sales amount for the year 2024.
• The main query then selects from TotalSales and filters the result to only include totals
greater than 500.
• The result would show that the total sales for 2024 exceed 500.
Output:
TotalAmount
1000
03. Inline CTE:
Inline CTEs (Common Table Expressions) are a way to define a temporary result set directly
within a SQL query for immediate use. They are referred to as "inline" because they are defined
and used directly within the scope of a single query, allowing for concise, readable SQL code
without creating a permanent table or repeating subquery logic.
Syntax:
WITH CTE_Name AS (
SELECT <columns>
FROM <table_name>
WHERE <conditions>
)
SELECT <columns>
FROM CTE_Name
WHERE <additional_conditions>;
WITH CustomerSales AS (
SELECT CustomerID, SUM(SaleAmount) AS TotalSales
FROM Sales
GROUP BY CustomerID
)
SELECT CustomerID, TotalSales
FROM CustomerSales
WHERE TotalSales >= 600;
Explanation:
1. The CTE named CustomerSales calculates the total sales for each customer.
2. The main query filters the results to show only customers with total sales >= 600.
CustomerID TotalSales
101 700
103 700
WITH CTE1 AS (
SELECT <columns>
FROM <table_name>
WHERE <conditions>
),
CTE2 AS (
SELECT <columns>
FROM CTE1
WHERE <conditions>
),
CTE3 AS (
SELECT <columns>
FROM <table_name>
WHERE <conditions>
)
SELECT <columns>
FROM CTE2
JOIN CTE3 ON <condition>;
Example 1: Aggregating Data Across Multiple CTEs
Table: Orders
Query:
Let’s calculate:
1. Total order amount for each customer (using CTE1).
2. Customers with total order amounts greater than 600 (using CTE2).
WITH CTE1 AS (
SELECT CustomerID, SUM(OrderAmount) AS TotalOrderAmount
FROM Orders
GROUP BY CustomerID
),
CTE2 AS (
SELECT CustomerID, TotalOrderAmount
FROM CTE1
WHERE TotalOrderAmount > 600
)
SELECT CustomerID, TotalOrderAmount
FROM CTE2;
Result:
CustomerID TotalOrderAmount
101 700
103 700
05. Materialized CTE:
Materialized CTEs are a concept introduced in some database systems (e.g., Snowflake,
PostgreSQL starting with version 12) to improve query performance. When a CTE is materialized,
the results of the CTE are computed once and temporarily stored (similar to a temporary table)
for reuse in subsequent parts of the query. This avoids recomputation of the CTE when it is
referenced multiple times.
Key Characteristics:
Reusability: The result of a materialized CTE is cached, so it is not recalculated every time it's
used.
Performance Boost: Materialization can significantly improve performance in complex queries
where the same CTE is referenced multiple times.
Explicit Materialization: Some databases allow you to explicitly request materialization, while
others decide automatically.
Syntax in PostgreSQL
In PostgreSQL, materialization of a CTE can be enforced using the MATERIALIZED keyword.
Conversely, the NOT MATERIALIZED keyword forces inlining (where the CTE is recalculated
every time it’s used).
Output:
ProductID TotalRevenue
101 600
103 500