SQLнавыкикод-ревьюаналитика

Как читать и разбирать чужой SQL-запрос

2026-07-11 6 мин

Чужой SQL-запрос на 120 строк с четырьмя CTE и тремя вложенными подзапросами — это то, с чем аналитик сталкивается в первую же неделю на новой работе. Кто-то уволился, остался дашборд, и надо понять, что этот запрос считает и почему цифра разошлась с реальностью. Разберу метод, которым пользуюсь сам: он превращает «стену текста» в понятную последовательность шагов.

С чего начать разбор незнакомого запроса?

Не читайте сверху вниз. SQL пишется не в том порядке, в котором выполняется. Глаз цепляется за первый SELECT, а движок начинает с FROM и JOIN — то есть с того, откуда берутся данные и как они склеиваются.

Мой первый шаг всегда одинаковый: найти самый внешний FROM и выписать, какие таблицы участвуют. Не что считается, а что является источником. Дальше смотрю на GROUP BY — он говорит, какая гранулярность у результата. Одна строка на пользователя? На пользователя и день? На заказ? Гранулярность результата — половина понимания запроса, потому что все агрегаты (SUM, COUNT, AVG) считаются именно внутри этих групп.

Только после этого читаю SELECT — теперь понятно, что за колонки в нём и на каком уровне они агрегированы.

Как раскрутить вложенные подзапросы и CTE?

Вложенность читается изнутри наружу, как матрёшка. Самый глубокий подзапрос выполняется первым, его результат становится «виртуальной таблицей» для следующего уровня.

С CTE проще: блоки WITH name AS (...) — это именованные шаги, и читать их надо строго по порядку сверху вниз, будто это переменные в скрипте. Хороший приём — мысленно (или в комментарии) подписать каждый CTE одной фразой: «активные пользователи за месяц», «первый заказ каждого клиента», «выручка по дням». Когда у всех пяти CTE есть человеческие имена-смыслы, финальный SELECT, который их соединяет, читается за минуту.

Если запрос написан через вложенные подзапросы, а не CTE, я часто первым делом переписываю его на CTE — механически, без изменения логики. Читаемость вырастает в разы, и по дороге замечаешь, что два подзапроса делают почти одно и то же.

Что такое фан-аут и как его заметить?

Фан-аут (row multiplication) — самая частая скрытая ошибка в чужих запросах. Возникает, когда JOIN соединяет таблицы по ключу, который в правой таблице не уникален. Одна строка слева умножается на количество совпадений справа, и SUM внезапно завышается в разы.

Классический пример: джойним orders с order_items, а потом суммируем orders.total. У заказа три позиции — сумма заказа посчитается трижды.

Как замечаю: смотрю на каждый JOIN и спрашиваю, уникален ли ключ соединения в той таблице, к которой присоединяемся. Если сомневаюсь — быстрый чек:

SELECT order_id, COUNT(*)
FROM order_items
GROUP BY order_id
HAVING COUNT(*) > 1;

Если строки есть — ключ не уникален, и любой SUM выше по запросу под подозрением. Про механику соединений подробно разбирал в гайде по JOIN, а сам приём с HAVING COUNT(*) > 1 — базовый инструмент поиска дублей.

Как проверить, что запрос считает именно то, что кажется?

Понять запрос глазами — это гипотеза. Проверка — это данные. Я почти всегда декомпозирую: беру самый внутренний CTE или подзапрос, запускаю его отдельно и смотрю на 10 строк результата. Совпадает ли с моим представлением? Потом добавляю следующий слой и снова смотрю. Так ошибка локализуется на конкретном шаге, а не «где-то в 120 строках».

Второй приём — проверка на одном известном объекте. Беру конкретного пользователя или заказ, про которого точно знаю ответ (посчитал руками или из другого источника), и прогоняю запрос с фильтром только на него. Если запрос выдаёт то же число — доверия больше. Если нет — вот он, баг.

Отрабатывать это удобно на живых данных: в SQL-тренажёре можно запускать запросы по шагам и сразу видеть результат каждого CTE, а не гадать по тексту.

Какие типичные ошибки прячутся в чужом SQL?

Помимо фан-аута, вот что встречаю чаще всего:

Все четыре ошибки роднит одно: запрос выполняется без ошибки и возвращает правдоподобное число — просто неправильное. Поэтому чтение чужого SQL — это не только «понять синтаксис», но и «проверить логику на данных».

Хотите закрепить навык — на собеседовании аналитика чтение и отладка чужого запроса встречается едва ли не чаще, чем написание своего с нуля. А если хочется системно разложить SQL по полочкам, есть бесплатный курс с нуля — от SELECT до оконных функций.

Отработай чтение SQL на практике
545 SQL-задач в браузере с автопроверкой — первые открыты без регистрации.
Открыть SQL-тренажёр →