A Common Table Expression (CTE) is a temporary, named result set defined with the WITH keyword that exists only for the duration of a single SQL statement. CTEs improve readability, enable recursion, and let you reference the same intermediate result multiple times without repeating code.
A Common Table Expression (CTE) is a temporary, named result set defined with the WITH
keyword that exists only for the duration of a single query. Databases treat a CTE like an inline view, letting you reference it multiple times without duplicating logic.
CTEs improve readability by giving the subquery a descriptive name, reduce duplication when the same derived table is needed more than once, and enable recursion—something regular subqueries cannot do.
Place WITH cte_name AS (SELECT ...)
before the main SELECT, UPDATE, INSERT, or DELETE statement. You can define multiple CTEs by separating them with commas.
Yes. Each CTE can reference earlier CTEs in the same WITH clause, allowing you to build complex logic step-by-step while keeping each step short and clear.
A CTE lives only for the duration of the single statement that follows the WITH clause. After execution, it disappears and consumes no additional memory or storage.
CTEs themselves do not guarantee faster queries. They can reduce duplication, which may help the optimizer, but performance depends on execution plans. Treat CTEs as a readability tool first.
A recursive CTE references itself to iterate over hierarchical data such as org charts or folder trees. It consists of an anchor query that sets the starting rows and a recursive query that repeatedly joins back to the CTE.
Use recursive CTEs when you need to traverse parent-child relationships of unknown depth, build running totals, or generate sequences without stored procedures.
Typical use cases include simplifying multi-step aggregations, reusing complex joins across several parts of a query, isolating business logic, performing recursion, and preparing data for window functions.
Most relational databases allow UPDATE, DELETE, or INSERT operations that target the rows returned by a CTE, offering a concise, set-based alternative to cursors.
Name each CTE descriptively, keep columns minimal, avoid nesting CTEs too deeply, and test performance by comparing CTEs versus inline subqueries or temp tables.
No. A CTE is virtual and query-scoped, while a temporary table is physically materialized and persists for the session unless dropped. Choose temp tables when you need indexes or repeated access across multiple queries.
CTEs can stage pre-aggregated or filtered data, making subsequent window functions simpler and faster to read by separating concerns into logical steps.
PostgreSQL, MySQL 8+, SQL Server, Oracle, SQLite, Snowflake, BigQuery, and most modern SQL engines support both non-recursive and recursive CTEs.
CTEs create named, query-scoped result sets that clarify logic and enable recursion. Use them to avoid duplication, enhance maintainability, and structure complex queries into readable steps. Test performance and follow naming conventions for maximum benefit.
No. A CTE is temporary and query-scoped, while a view is stored in the database catalog and reused across sessions.
You cannot declare a WITH inside another WITH clause, but you can reference earlier CTEs to create a chain—achieving similar layering without nesting.
Most databases impose no strict limit; practical limits come from query complexity and readability. Keep the chain manageable.
Yes, starting from MySQL 8.0, both non-recursive and recursive CTEs are fully supported.