← Назад к вопросам

Что такое CTE запрос?

1.0 Junior🔥 164 комментариев
#Основы C# и .NET

Комментарии (4)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое CTE (Common Table Expression)

CTE (Common Table Expression), или обобщённое табличное выражение — это временный именованный набор результатов, который можно ссылаться в рамках оператора SELECT, INSERT, UPDATE, DELETE или CREATE VIEW. CTE существует только во время выполнения запроса и является мощным инструментом для структурирования сложных SQL-запросов.

Ключевые характеристики и синтаксис

Базовый синтаксис CTE в SQL Server (аналогичен в других СУБД с небольшими отличиями):

WITH CTE_Название (Столбец1, Столбец2, ...)
AS
(
    -- Определение CTE (подзапрос)
    SELECT Столбец1, Столбец2
    FROM ИсходнаяТаблица
    WHERE Условие
)
-- Основной запрос, использующий CTE
SELECT *
FROM CTE_Название;

Основные преимущества CTE

  1. Улучшение читаемости и поддерживаемости:

    • Позволяют разбивать сложные запросы на логические блоки
    • Делают код более структурированным и понятным
    • Упрощают отладку многоступенчатых запросов
  2. Возможность рекурсии:

    • Рекурсивные CTE — уникальная возможность для иерархических данных
    • Позволяют обрабатывать деревья и графы (организационные структуры, категории товаров)
    WITH РекурсивнаяCTE AS
    (
        -- Якорный член
        SELECT Id, ParentId, Name, 1 AS Уровень
        FROM Категории
        WHERE ParentId IS NULL
        
        UNION ALL
        
        -- Рекурсивный член
        SELECT c.Id, c.ParentId, c.Name, рц.Уровень + 1
        FROM Категории c
        INNER JOIN РекурсивнаяCTE рц ON c.ParentId = рц.Id
    )
    SELECT * FROM РекурсивнаяCTE;
    
  3. Замена представлений (Views):

    • CTE можно использовать вместо временных представлений
    • Не требуют создания объектов в базе данных
    • Идеальны для одноразовых сложных запросов

Практическое применение в Backend-разработке на C#

Использование с Entity Framework Core:

// Пример использования CTE через FromSqlRaw в EF Core
var hierarchicalData = await context.Categories
    .FromSqlRaw(@"
        WITH RecursiveCTE AS (
            SELECT Id, ParentId, Name, 0 AS Level
            FROM Categories
            WHERE ParentId IS NULL
            
            UNION ALL
            
            SELECT c.Id, c.ParentId, c.Name, r.Level + 1
            FROM Categories c
            INNER JOIN RecursiveCTE r ON c.ParentId = r.Id
        )
        SELECT * FROM RecursiveCTE
        ORDER BY Level, Name
    ")
    .ToListAsync();

// Альтернативно через Dapper
using var connection = new SqlConnection(connectionString);
var result = await connection.QueryAsync<CategoryDto>(
    @"
    WITH EmployeeCTE AS (
        SELECT Id, Name, ManagerId, Salary,
               ROW_NUMBER() OVER (ORDER BY Salary DESC) AS Rank
        FROM Employees
        WHERE DepartmentId = @DepartmentId
    )
    SELECT * FROM EmployeeCTE WHERE Rank <= 10
    ",
    new { DepartmentId = departmentId }
);

Ограничения и особенности CTE

  • Время жизни: CTE существует только в рамках выполнения запроса
  • Порядок выполнения: Определяется до основного запроса, но оптимизатор СУБД может переупорядочивать
  • Производительность: Не создаёт индексов, но может быть материализована в некоторых СУБД
  • Множественные CTE: Можно объявлять несколько CTE в одном выражении WITH
WITH 
CTE1 AS (SELECT * FROM Table1 WHERE Condition1),
CTE2 AS (SELECT * FROM Table2 WHERE Condition2),
CTE3 AS (SELECT CTE1.*, CTE2.ColumnX FROM CTE1 JOIN CTE2 ON ...)
SELECT * FROM CTE3;

Сравнение с альтернативами

КритерийCTEВременные таблицыПодзапросы
Время жизниОдин запросСессия/транзакцияОдин запрос
ПроизводительностьЗависит от СУБДИндексируемыМогут быть неэффективны
ЧитаемостьВысокаяСредняяНизкая (для сложных)
Возможность рекурсииДаНетНет

Рекомендации по использованию

  1. Для иерархических данных всегда предпочитайте рекурсивные CTE каскадным запросам
  2. При многоэтапных преобразованиях данных используйте несколько CTE для ясности
  3. Для аналитических запросов CTE идеальны для подготовки промежуточных агрегаций
  4. Избегайте излишней вложенности — если CTE становится слишком сложной, рассмотрите временную таблицу

В контексте C# Backend-разработки понимание CTE критически важно для:

  • Эффективной работы с Entity Framework Core через raw SQL
  • Оптимизации запросов к базе данных
  • Реализации сложной бизнес-логики на уровне БД
  • Создания эффективных хранимых процедур и аналитических отчётов

CTE представляет собой баланс между производительностью, читаемостью и гибкостью, делая их незаменимым инструментом в арсенале backend-разработчика, работающего с реляционными базами данных.

Что такое CTE запрос? | PrepBro