[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-postgresql-chto-takoe-cte-common-table-expressions":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},1048,"chto-takoe-cte-common-table-expressions",28,"postgresql","PostgreSQL","🐘","Что такое CTE (Common Table Expressions)?","CTE (Common Table Expressions) — именованные подзапросы, определяемые в блоке `WITH`, которые улучшают читаемость сложных запросов и позволяют ссылаться на один и тот же подзапрос несколько раз.\n\n\u003Cdetails>\u003Csummary>Простой и составной CTE\u003C\u002Fsummary>\n\n```sql\n-- Простой CTE\nWITH large_accounts AS (\n    SELECT id, client_id, balance\n    FROM accounts\n    WHERE balance > 1000000\n)\nSELECT c.name, la.balance\nFROM large_accounts la\nJOIN clients c ON c.id = la.client_id;\n\n-- Несколько CTE\nWITH\ndebits AS (\n    SELECT account_id, sum(amount) AS total_debit\n    FROM transactions\n    WHERE type = 'DEBIT' AND created_at > '2024-01-01'\n    GROUP BY account_id\n),\ncredits AS (\n    SELECT account_id, sum(amount) AS total_credit\n    FROM transactions\n    WHERE type = 'CREDIT' AND created_at > '2024-01-01'\n    GROUP BY account_id\n)\nSELECT\n    a.id,\n    COALESCE(d.total_debit, 0) AS total_debit,\n    COALESCE(c.total_credit, 0) AS total_credit,\n    COALESCE(c.total_credit, 0) - COALESCE(d.total_debit, 0) AS net_flow\nFROM accounts a\nLEFT JOIN debits d ON d.account_id = a.id\nLEFT JOIN credits c ON c.account_id = a.id;\n```\n\n\u003C\u002Fdetails>\n\n### Рекурсивный CTE\n\n```sql\n-- Иерархия подразделений\nWITH RECURSIVE department_tree AS (\n    -- Якорный запрос (базовый случай)\n    SELECT id, name, parent_id, 1 AS level\n    FROM departments\n    WHERE parent_id IS NULL\n\n    UNION ALL\n\n    -- Рекурсивный запрос\n    SELECT d.id, d.name, d.parent_id, dt.level + 1\n    FROM departments d\n    JOIN department_tree dt ON d.parent_id = dt.id\n)\nSELECT * FROM department_tree ORDER BY level, name;\n```\n\n### CTE с модификацией данных\n\n```sql\n-- Удалить устаревшие записи и вернуть количество\nWITH deleted AS (\n    DELETE FROM sessions\n    WHERE expires_at \u003C now()\n    RETURNING *\n)\nSELECT count(*) AS deleted_count FROM deleted;\n```\n\n### Важно о производительности\n\n- До PostgreSQL 12 CTE были «барьером оптимизации» — планировщик не мог протолкнуть условия из внешнего запроса внутрь CTE\n- Начиная с PostgreSQL 12 CTE по умолчанию инлайнятся (встраиваются) в основной запрос, если используются один раз и не имеют побочных эффектов\n- Принудительная материализация: `WITH cte AS MATERIALIZED (...)`\n- Принудительный инлайн: `WITH cte AS NOT MATERIALIZED (...)`\n\n> **На собеседовании:** два ключевых момента: (1) рекурсивный CTE для обхода деревьев — WHERE RECURSIVE и UNION ALL, (2) изменение поведения в PostgreSQL 12 — CTE теперь инлайнятся, что может как улучшить, так и ухудшить производительность по сравнению с ожидаемым.","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Что такое CTE (Common Table Expressions)? — Gymterview","CTE (Common Table Expressions) — именованные подзапросы, определяемые в блоке `WITH`, которые улучшают читаемость сложных запросов и позволяют ссылаться на один","CTE (Common Table Expressions) — именованные подзапросы, определяемые в блоке `WITH`, которые улучшают читаемость сложны",[7,13],"CTE (Common Table Expressions) — именованные подзапросы, определяемые в блоке `WITH`, которые улучшают читаемость сложных запросов и позволяют ссылаться на один и тот же подзапрос несколько раз.",true]