Comprehensive Guide to Multiple WITH Statements and Nested CTEs in SQL

Nov 20, 2025 · Programming · 9 views · 7.8

Keywords: SQL | WITH_Statements | Common_Table_Expressions | CTE_Nesting | Recursive_Queries

Abstract: This technical article provides an in-depth analysis of correct syntax for multiple WITH statements in SQL, demonstrating practical code examples for defining multiple Common Table Expressions within single queries. Based on high-scoring Stack Overflow answers and authoritative technical documentation, the article systematically explains WITH clause syntax rules, common error avoidance methods, and implementation principles of recursive queries, offering complete technical reference for database developers.

Basic Syntax Structure of Multiple WITH Statements

In SQL Server, when using multiple WITH statements to define Common Table Expressions, specific syntax rules must be followed. According to the best answer from the Q&A data, the correct syntax requires all CTE definitions to follow a single WITH keyword, separated by commas between expression definitions.

WITH DependencedIncidents AS
(
    SELECT INC.[RecTime],INC.[SQL] AS [str] FROM
    (
        SELECT A.[RecTime] As [RecTime],X.[SQL] As [SQL] FROM [EventView] AS A 
        CROSS JOIN [Incident] AS X
            WHERE
                patindex('%' + A.[Col] + '%', X.[SQL]) > 0
    ) AS INC
),
lalala AS
(
    SELECT INC.[RecTime],INC.[SQL] AS [str] FROM
    (
        SELECT A.[RecTime] As [RecTime],X.[SQL] As [SQL] FROM [EventView] AS A 
        CROSS JOIN [Incident] AS X
            WHERE
                patindex('%' + A.[Col] + '%', X.[SQL]) > 0
    ) AS INC
)
SELECT * FROM DependencedIncidents
UNION ALL
SELECT * FROM lalala;

Common Error Analysis and Solutions

The "Error near With" encountered in the original question stems from repeated use of the WITH keyword. In SQL syntax, the WITH clause can only appear once, and subsequent CTE definitions must be connected to the previous CTE using commas. This design ensures logical clarity and syntactic consistency in queries.

Error example demonstrating incorrect syntax:

-- Incorrect approach: duplicate WITH keywords
With DependencedIncidents AS (...)
With lalala AS (...)

Correct approach combining all CTE definitions:

-- Correct approach: single WITH, multiple CTEs comma-separated
WITH DependencedIncidents AS (...),
lalala AS (...)

CTE Nesting Reference Mechanism

Common Table Expressions support referencing previously defined CTEs in subsequent CTEs. This nesting reference mechanism significantly enhances the expressive power of SQL queries. As described in the reference article, this design allows for building complex data processing pipelines.

The following example demonstrates dependency relationships between CTEs:

WITH base_data AS (
    SELECT country, product_family, 
           SUM(qty_exported * unit_price) AS total_exports
    FROM product
    GROUP BY country, product_family
),
country_totals AS (
    SELECT country, SUM(total_exports) AS total_exports_country
    FROM base_data
    GROUP BY country
)
SELECT bd.country, bd.product_family, bd.total_exports,
       ROUND((bd.total_exports / ct.total_exports_country) * 100, 2) AS percentage
FROM base_data bd
JOIN country_totals ct ON bd.country = ct.country;

Advanced Applications of Recursive CTEs

One of the most powerful features of CTEs is support for recursive queries, which is particularly important when processing hierarchical data. Recursive CTEs consist of anchor members and recursive members connected by UNION ALL.

Employee hierarchy query example:

WITH RECURSIVE company_hierarchy AS (
    -- Anchor member: top-level managers
    SELECT employee_id, firstname, lastname, 
           manager_employee_id, 0 AS hierarchy_level
    FROM employees
    WHERE manager_employee_id IS NULL
    
    UNION ALL
    
    -- Recursive member: subordinate employees
    SELECT e.employee_id, e.firstname, e.lastname,
           e.manager_employee_id, ch.hierarchy_level + 1
    FROM employees e
    INNER JOIN company_hierarchy ch ON e.manager_employee_id = ch.employee_id
)
SELECT * FROM company_hierarchy
ORDER BY hierarchy_level, employee_id;

Performance Considerations and Best Practices

While CTEs provide excellent code readability and modularization capabilities, they should be used cautiously in performance-sensitive scenarios. CTEs are re-executed each time they are referenced, which differs from the one-time creation of temporary tables. For complex multi-level nested CTEs, it is recommended to:

Practical Application Scenario Analysis

Based on the specific case in the Q&A data, we can observe the practical application of multiple CTEs in event analysis. The original query implements event correlation analysis based on pattern matching through CROSS JOIN and patindex functions. This architecture holds significant value in log analysis and security monitoring scenarios.

Optimized query structure:

WITH EventPatterns AS (
    SELECT A.[RecTime], A.[Col], X.[SQL]
    FROM [EventView] AS A
    CROSS JOIN [Incident] AS X
    WHERE patindex('%' + A.[Col] + '%', X.[SQL]) > 0
),
CategorizedIncidents AS (
    SELECT [RecTime], [SQL] AS incident_details,
           CASE 
               WHEN [SQL] LIKE '%error%' THEN 'Error'
               WHEN [SQL] LIKE '%warning%' THEN 'Warning'
               ELSE 'Info'
           END AS severity
    FROM EventPatterns
)
SELECT * FROM CategorizedIncidents
ORDER BY [RecTime] DESC;

Through reasonable CTE layered design, complex data processing logic can be decomposed into multiple clear steps, significantly improving code maintainability and readability.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.