Порядок выполнения SQL-запроса
Один из самых частых вопросов: в каком порядке СУБД на самом деле выполняет части запроса.
Логический порядок выполнения — последовательность, в которой СУБД «обрабатывает» части запроса:
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Он отличается от порядка, в котором вы их пишете.
Вопрос с собеседования
«Вы пишете SELECT первым, но почему в WHERE нельзя сослаться на алиас из SELECT?» — классическая проверка понимания. Ответ: потому что WHERE вычисляется раньше, чем SELECT, и алиас в этот момент ещё не существует.
Логический порядок
Запрос вы читаете и пишете в одном порядке, а СУБД выполняет его в другом — логическом:
FROM(иJOIN) — берём и соединяем таблицы;WHERE— фильтруем отдельные строки;GROUP BY— собираем строки в группы;HAVING— фильтруем уже группы;SELECT— вычисляем выражения и алиасы;ORDER BY— сортируем результат;LIMIT— отрезаем нужное число строк.
Из этого порядка вытекают почти все «каверзные» правила SQL. Например, в WHERE нельзя использовать агрегат COUNT(*) — группы ещё не созданы. А вот ORDER BY по алиасу из SELECT работает, потому что сортировка идёт последней.
Проверим на живом примере
Алиас total создан в SELECT. Сортировать по нему можно (ORDER BY — после SELECT), а вот фильтровать им в WHERE было бы ошибкой.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer TEXT,
amount INTEGER
);
INSERT INTO orders (customer, amount) VALUES
('Аня', 500),
('Аня', 300),
('Борис', 900),
('Вера', 200);
SELECT customer, SUM(amount) AS total
FROM orders
GROUP BY customer
HAVING SUM(amount) > 400
ORDER BY total DESC;
Вывод:
Борис|900 Аня|800
Здесь видно весь конвейер: FROM взял таблицу, GROUP BY собрал заказы по клиентам, HAVING отсёк тех, у кого сумма ≤ 400, SELECT посчитал total, а ORDER BY отсортировал по этому алиасу.
Почему это важно знать
Понимание порядка — это не academическая мелочь. Оно сразу объясняет три типичные ошибки новичков: «почему алиас не виден в WHERE», «почему агрегат нельзя в WHERE» и «чем WHERE отличается от HAVING». На собеседовании ждут именно связной картины, а не заученного списка.
Итог
- Пишем
SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY, а выполняется это в порядкеFROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. - Алиасы из
SELECTдоступны вORDER BY, но не вWHEREи не вGROUP BY. - Агрегаты нельзя в
WHERE— для фильтра по агрегату естьHAVING.