Все материалы
Продуктовая аналитикапрактикумсредний

Порядок выполнения SQL-запроса: почему WHERE не видит alias из SELECT

Разбираем логический порядок выполнения SQL-запроса: FROM, WHERE, GROUP BY, HAVING, SELECT и ORDER BY. Примеры помогают понять ошибки alias и агрегации.

КПКейсПрактика21 июля 2026 г.8 мин

Запрос часто читают как инструкцию: сначала SELECT, потом WHERE, затем сортировка. Из-за этого появляются знакомые ошибки: псевдоним из SELECT нельзя использовать в WHERE, агрегат нельзя фильтровать обычным WHERE, а LIMIT не спасает от дорогого сканирования таблицы. Понимание порядка не заменяет план выполнения, но быстро объясняет большую часть логики запроса. Разберём вопрос на одном запросе: Почему SQL написан сверху вниз, но база данных логически обрабатывает его в другом порядке?

Сначала определим задачу

Почему SQL написан сверху вниз, но база данных логически обрабатывает его в другом порядке?

Допустим, нужно найти каналы с выручкой выше 100 000 ₽. WHERE работает со строками заказов до группировки, поэтому условие по SUM(revenue) появляется в HAVING. А псевдоним revenue_total создаётся только на шаге SELECT и не существует на этапе WHERE или HAVING в большинстве диалектов.

сначала зерно, потом запрос

Если вопрос касается отдельных записей, начинай с WHERE. Если он касается результата агрегирования, используй HAVING. Если alias нужен для фильтра или повторного расчёта, подними вычисление на уровень CTE. Такая схема превращает порядок SQL в рабочую карту, а не в список исключений.

Как работает конструкция

Для аналитика полезно различать текстовый порядок и логический. Сначала определяется источник строк и соединения, затем отбрасываются записи, формируются группы, фильтруются группы, вычисляются выражения SELECT и только потом применяется сортировка и ограничение выдачи. Оптимизатор может физически переставлять операции, сохраняя тот же результат.

Перед исправлением запроса запиши зерно результата: одна строка — канал за месяц. Потом укажи, какие условия относятся к строкам, а какие к уже собранным группам. Если вычисление нужно использовать повторно, вынеси его в CTE или подзапрос. Так alias станет колонкой следующего отношения, а не магическим именем внутри текущего SELECT.

  • Зафиксируй одну строку результата.
  • Отдели условия по исходным строкам от условий по рассчитанным значениям.
  • Назови период, ключи связи и правило для повторов.

Запрос по шагам

Названия таблиц здесь условные. При переносе сохрани зерно и бизнес-условия, а не буквальный синтаксис примера.

Пример: alias агрегата фильтруется во внешнем запросе
WITH channel_month AS (
  SELECT channel, date_trunc('month', paid_at) AS month, SUM(amount) AS revenue_total
  FROM orders
  WHERE paid_at >= DATE '2026-01-01' AND status = 'paid'
  GROUP BY channel, date_trunc('month', paid_at)
)
SELECT channel, month, revenue_total
FROM channel_month
WHERE revenue_total > 100000
ORDER BY month, revenue_total DESC;

Проверка результата

Собери пять-десять строк, где ответ можно получить вручную. Добавь NULL, дубль, объект без связанной записи и значение на границе периода. Затем сравни число строк и уникальных ключей до и после спорного шага.

Выполненный без ошибки запрос ещё не является правильным. Другой аналитик должен суметь восстановить из него источник, фильтр, grain и ожидаемое поведение на крайних случаях.

Логический порядок SQL
ШагОператорВопрос
1FROM / JOINоткуда берём строки?
2WHEREкакие строки оставить?
3GROUP BYкак собрать группы?
4HAVINGкакие группы оставить?
5SELECTчто показать?
6ORDER BY / LIMITкак представить результат?

Границы и альтернативы

Не путай логический порядок с гарантированным физическим планом. Не рассчитывай на порядок строк без ORDER BY. Не используй HAVING для обычного фильтра по исходной таблице: это ухудшает читаемость и иногда увеличивает объём работы. И помни, что оконная функция вычисляется после группировки, поэтому её нельзя бездумно ставить в WHERE того же уровня.

Если вопрос касается отдельных записей, начинай с WHERE. Если он касается результата агрегирования, используй HAVING. Если alias нужен для фильтра или повторного расчёта, подними вычисление на уровень CTE. Такая схема превращает порядок SQL в рабочую карту, а не в список исключений.

Сколько строк проходит через этапы запроса

Условный поток для отчёта по заказам: каждый этап меняет зерно или число строк.

Строк или групп

Задание для самостоятельной проверки

Возьми отчёт по заказам и перепиши его в два шага: сначала CTE с дневной выручкой, затем внешний SELECT с фильтром и сортировкой. Отдельно подпиши, где находятся фильтры строк, фильтры групп и логика представления. Это простая привычка, которая заметно снижает число ошибок в больших запросах.

  • Сначала запиши ожидаемый результат словами.
  • Проверь запрос на маленькой контрольной выборке.
  • Объясни, что запрос считает и чего не доказывает.

Решение для команды

Если вопрос касается отдельных записей, начинай с WHERE. Если он касается результата агрегирования, используй HAVING. Если alias нужен для фильтра или повторного расчёта, подними вычисление на уровень CTE. Такая схема превращает порядок SQL в рабочую карту, а не в список исключений.

Продолжить чтение
Вся библиотека