SQL Tutorial
SQL Clauses / Operators
SQL-Injection
SQL Functions
SQL Queries
PL/SQL
MySQL
SQL Server
Misc
The WITH
clause, often referred to as Common Table Expressions (CTEs), provides a way to temporarily create a named result set that can be referred to within a main query. The WITH
clause can be used for breaking down complex queries into simpler parts, allowing better readability and maintenance, and can also be used for recursive queries.
WITH cte_name (column_name1, column_name2, ...) AS ( -- Your subquery here ) -- Main query using the CTE SELECT ... FROM cte_name ...
Suppose you want to get the average salary from an employees
table and then find out which employees earn more than the average.
Without CTE:
SELECT name, salary FROM employees WHERE salary > ( SELECT AVG(salary) FROM employees );
Using the WITH
clause:
WITH AverageSalary AS ( SELECT AVG(salary) AS avg_sal FROM employees ) SELECT name, salary FROM employees WHERE salary > (SELECT avg_sal FROM AverageSalary);
One of the most powerful features of CTEs is their ability to be recursive. This is very useful for tasks like hierarchy traversal.
Consider a table hierarchy
that has an id
, parent_id
, and name
. Here's an example of a recursive CTE to find all descendants of a particular item:
WITH RECURSIVE Descendants AS ( SELECT id, parent_id, name FROM hierarchy WHERE parent_id = [given_id] UNION ALL SELECT h.id, h.parent_id, h.name FROM hierarchy h INNER JOIN Descendants d ON h.parent_id = d.id ) SELECT * FROM Descendants;
In summary, the WITH
clause or CTEs provide a convenient way to structure and organize complex SQL queries, making them more readable and maintainable. They're especially useful for recursive tasks and for replacing repetitive subqueries.
How to Use WITH
in SQL:
WITH
clause, also known as a Common Table Expression (CTE), is used to define a temporary result set that can be referred to within a SELECT, INSERT, UPDATE, or DELETE statement.-- Using WITH in SQL WITH temp_table AS ( SELECT column1, column2 FROM some_table ) SELECT * FROM temp_table;
Creating Common Table Expressions with WITH
:
WITH
to define a named temporary result set.-- Creating a CTE with WITH WITH employee_names AS ( SELECT employee_id, first_name, last_name FROM employees ) SELECT * FROM employee_names;
Recursive Common Table Expressions in SQL:
UNION
or UNION ALL
operator.-- Recursive CTE for hierarchical data WITH recursive_category AS ( SELECT category_id, category_name, parent_category_id FROM categories WHERE parent_category_id IS NULL UNION ALL SELECT c.category_id, c.category_name, c.parent_category_id FROM categories c JOIN recursive_category rc ON c.parent_category_id = rc.category_id ) SELECT * FROM recursive_category;
WITH
and SELECT, INSERT, UPDATE, DELETE Statements:
-- Using CTE with SELECT WITH high_salary_employees AS ( SELECT employee_id, first_name, last_name FROM employees WHERE salary > 80000 ) SELECT * FROM high_salary_employees; -- Using CTE with INSERT WITH new_employee AS ( VALUES (101, 'John', 'Doe', 90000) ) INSERT INTO employees (employee_id, first_name, last_name, salary) SELECT * FROM new_employee; -- Using CTE with UPDATE WITH salary_increase AS ( SELECT employee_id, salary * 1.1 AS new_salary FROM employees WHERE department_id = 10 ) UPDATE employees SET salary = si.new_salary FROM salary_increase si WHERE employees.employee_id = si.employee_id;
Aliasing Columns in WITH
Clauses:
-- Aliasing columns in CTE WITH emp AS ( SELECT employee_id AS emp_id, first_name AS emp_first_name FROM employees ) SELECT * FROM emp;
WITH
and JOIN Operations in SQL:
-- Using CTE with JOIN WITH employee_department AS ( SELECT e.employee_id, e.first_name, e.last_name, d.department_name FROM employees e JOIN departments d ON e.department_id = d.department_id ) SELECT * FROM employee_department;
Using Multiple WITH
Clauses in a Query:
-- Using multiple CTEs in a query WITH cte1 AS ( SELECT * FROM table1 ), cte2 AS ( SELECT * FROM table2 ) SELECT * FROM cte1 JOIN cte2 ON cte1.id = cte2.id;
Handling NULL Values in WITH
Clauses:
-- Handling NULL values in CTE WITH clean_data AS ( SELECT COALESCE(column1, 'N/A') AS cleaned_column FROM table1 ) SELECT * FROM clean_data;
Using WITH
and Window Functions in SQL:
-- Using CTE with window function WITH ranked_employees AS ( SELECT employee_id, first_name, last_name, RANK() OVER (ORDER BY salary DESC) AS salary_rank FROM employees ) SELECT * FROM ranked_employees;
WITH
vs. Subqueries in SQL:
-- Using CTE vs. subquery WITH high_salary_employees AS ( SELECT employee_id, first_name, last_name FROM employees WHERE salary > 80000 ) SELECT * FROM high_salary_employees; -- Equivalent subquery SELECT employee_id, first_name, last_name FROM employees WHERE salary > 80000;
Using WITH
in Complex Queries:
-- Using CTE in a complex query WITH revenue_data AS ( -- Some complex query logic here ), customer_data AS ( -- Another complex query logic here ) SELECT * FROM revenue_data JOIN customer_data ON revenue_data.customer_id = customer_data.customer_id;
Practical Examples of Using WITH
in SQL Queries:
-- Practical example using CTE WITH employee_hierarchy AS ( SELECT employee_id, manager_id, CONNECT_BY_ROOT employee_id AS top_manager_id FROM employees CONNECT BY PRIOR employee_id = manager_id ) SELECT * FROM employee_hierarchy;