[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-sql-chto-takoe-cte-common-table-expression":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},875,"chto-takoe-cte-common-table-expression",25,"sql","SQL","🗃️","Что такое CTE (Common Table Expression)?","CTE (Common Table Expression) — именованное временное результирующее множество, определяемое с помощью ключевого слова `WITH`. CTE существует только в рамках одного запроса и делает сложные запросы более читаемыми, позволяя разбить их на логические блоки.\n\n### Базовый синтаксис\n\n```sql\nWITH cte_name AS (\n    SELECT column1, column2\n    FROM table_name\n    WHERE condition\n)\nSELECT * FROM cte_name;\n```\n\n### Пример: средняя зарплата по отделам\n\n```sql\nWITH dept_avg AS (\n    SELECT department, AVG(salary) AS avg_salary\n    FROM employees\n    GROUP BY department\n)\nSELECT\n    e.name, e.department, e.salary,\n    d.avg_salary,\n    e.salary - d.avg_salary AS diff_from_avg\nFROM employees e\nJOIN dept_avg d ON e.department = d.department\nWHERE e.salary > d.avg_salary;\n```\n\n### Несколько CTE в одном запросе\n\n\u003Cdetails>\u003Csummary>Пример с несколькими CTE\u003C\u002Fsummary>\n\n```sql\nWITH\nactive_users AS (\n    SELECT user_id, name\n    FROM users\n    WHERE status = 'active'\n),\nuser_orders AS (\n    SELECT user_id, COUNT(*) AS order_count, SUM(amount) AS total_amount\n    FROM orders\n    WHERE order_date >= '2026-01-01'\n    GROUP BY user_id\n)\nSELECT\n    au.name,\n    COALESCE(uo.order_count, 0) AS order_count,\n    COALESCE(uo.total_amount, 0) AS total_amount\nFROM active_users au\nLEFT JOIN user_orders uo ON au.user_id = uo.user_id\nORDER BY total_amount DESC;\n```\n\n\u003C\u002Fdetails>\n\n### Рекурсивные CTE\n\nРекурсивные CTE позволяют выполнять иерархические запросы — обход деревьев, графов, организационных структур.\n\n```sql\nWITH RECURSIVE cte_name AS (\n    -- Базовый (якорный) запрос\n    SELECT ...\n    UNION ALL\n    -- Рекурсивный запрос (ссылается на cte_name)\n    SELECT ... FROM cte_name WHERE ...\n)\nSELECT * FROM cte_name;\n```\n\n\u003Cdetails>\u003Csummary>Пример: организационная иерархия\u003C\u002Fsummary>\n\n```sql\nWITH RECURSIVE org_tree AS (\n    -- Якорь: генеральный директор (нет руководителя)\n    SELECT id, name, manager_id, 1 AS level\n    FROM employees\n    WHERE manager_id IS NULL\n\n    UNION ALL\n\n    -- Рекурсия: подчинённые каждого руководителя\n    SELECT e.id, e.name, e.manager_id, ot.level + 1\n    FROM employees e\n    JOIN org_tree ot ON e.manager_id = ot.id\n)\nSELECT\n    REPEAT('  ', level - 1) || name AS org_chart,\n    level\nFROM org_tree\nORDER BY level, name;\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\u003Csummary>Пример: генерация ряда дат\u003C\u002Fsummary>\n\n```sql\nWITH RECURSIVE dates AS (\n    SELECT DATE '2026-01-01' AS dt\n    UNION ALL\n    SELECT dt + INTERVAL '1 day'\n    FROM dates\n    WHERE dt \u003C DATE '2026-12-31'\n)\nSELECT dt FROM dates;\n```\n\n\u003C\u002Fdetails>\n\n### CTE vs подзапрос vs временная таблица\n\n| Характеристика | CTE | Подзапрос | Временная таблица |\n|---|---|---|---|\n| Область видимости | Один запрос | Внутри внешнего запроса | Сессия \u002F транзакция |\n| Повторное использование | Можно ссылаться несколько раз в одном запросе | Нужно дублировать | Можно в разных запросах |\n| Рекурсия | Поддерживается | Нет | Нет (нужен цикл) |\n| Индексы | Нет | Нет | Можно создать |\n| Материализация | Зависит от оптимизатора | Зависит от оптимизатора | Всегда материализована |\n| Читаемость | Высокая | Низкая при вложенности | Средняя |\n\n### Важное\n\n- В PostgreSQL CTE может быть материализованным или нет — оптимизатор решает сам. Можно управлять явно: `WITH cte AS MATERIALIZED (...)` или `WITH cte AS NOT MATERIALIZED (...)`\n- Рекурсивные CTE обязательно должны иметь условие завершения, иначе запрос зациклится\n- CTE может использоваться в `SELECT`, `INSERT`, `UPDATE`, `DELETE`\n- В PostgreSQL рекурсивный CTE требует ключевого слова `RECURSIVE`, даже если только один из нескольких CTE является рекурсивным\n\n### Частые ошибки\n\n- Забывают ключевое слово `RECURSIVE` для рекурсивных CTE в PostgreSQL\n- Отсутствие условия завершения рекурсии — приводит к бесконечному циклу\n- Предполагают, что CTE всегда материализуется (как в PostgreSQL до 12) — в новых версиях оптимизатор может «встроить» (inline) CTE\n- Используют CTE там, где достаточно простого подзапроса — избыточное усложнение\n\n> **На собеседовании:** объясните, что CTE — это именованный подзапрос для читаемости и повторного использования. Обязательно упомяните рекурсивные CTE и приведите пример (обход дерева). Частая ошибка — не знать разницу между CTE и временной таблицей.","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Что такое CTE (Common Table Expression)? — Gymterview","CTE (Common Table Expression) — именованное временное результирующее множество, определяемое с помощью ключевого слова `WITH`. CTE существует только в рамках од","CTE (Common Table Expression) — именованное временное результирующее множество, определяемое с помощью ключевого слова `",[7,13],"CTE (Common Table Expression) — именованное временное результирующее множество, определяемое с помощью ключевого слова `WITH`. CTE существует только в рамках одного запроса и делает сложные запросы более читаемыми, позволяя разбить их на логические блоки.",true]