Проблема вложенных подзапросов
Зачем это нужно
Вложенные подзапросы — одна из самых частых причин, по которым SQL-код становится нечитаемым. Посмотри на этот запрос:
SELECT client_id, total_amount
FROM (
SELECT a.client_id, SUM(t.amount) AS total_amount
FROM (
SELECT id, client_id FROM accounts WHERE account_type = 'текущий'
) a
JOIN transactions t ON t.account_id = a.id
WHERE t.txn_type = 'пополнение'
GROUP BY a.client_id
) sub
WHERE total_amount > 50000
ORDER BY total_amount DESC;
Что здесь происходит? Чтобы понять, нужно читать снизу вверх, держа в голове три уровня вложенности. Если через месяц тебе понадобится изменить фильтр — удачи.
Антипаттерны вложенных подзапросов
Проблема 1: Нечитаемость. Скобки закрываются далеко от того места, где открывались. Нельзя дать подзапросу осмысленное имя.
Проблема 2: Дублирование. Если один и тот же подзапрос нужен в нескольких местах запроса, его приходится копировать:
SELECT *
FROM (SELECT account_id, SUM(amount) FROM transactions GROUP BY account_id) t1
JOIN (SELECT account_id, SUM(amount) FROM transactions GROUP BY account_id) t2
ON t1.account_id = t2.account_id;
-- Один и тот же подзапрос дважды!
Проблема 3: Сложность отладки. Нельзя запустить подзапрос отдельно, чтобы проверить промежуточный результат.
Что такое CTE
CTE (Common Table Expression) — именованный временный результат, который определяется перед основным запросом и используется в нём как обычная таблица.
WITH имя_cte AS (
-- подзапрос
SELECT ...
)
SELECT * FROM имя_cte;
CTE — это не новая таблица в базе данных. Это способ дать имя подзапросу и вынести его «наверх» для читаемости.
Запомни
Вложенные подзапросы работают, но плохо читаются. CTE решают эту проблему: код пишется и читается сверху вниз, каждый блок имеет осмысленное имя.
Прочитайте урок до конца — прогресс засчитается автоматически