Какая последовательность выполнения команд SELECT, FROM, JOIN и WHERE в SQL?

Ответ

Логический порядок выполнения SQL-запроса (порядок обработки движком) отличается от порядка его написания. Вот последовательность:

  1. FROMJOIN) — сначала определяется исходный набор данных из таблиц и выполняются все соединения.
  2. WHERE — затем происходит фильтрация строк по заданным условиям.
  3. GROUP BY — строки группируются (если указано).
  4. HAVING — фильтруются уже сформированные группы (если указано).
  5. SELECT — выбираются, вычисляются и переименовываются столбцы, включая агрегатные функции.
  6. ORDER BY — результат сортируется.
  7. LIMIT / OFFSET — применяется ограничение на количество возвращаемых строк.

Почему это важно? Например, вы не можете использовать псевдоним столбца из SELECT в условии WHERE, потому что WHERE выполняется раньше, чем SELECT. Алиасы из SELECT доступны только в ORDER BY и HAVING.

Пример, иллюстрирующий порядок:

-- Порядок НАПИСАНИЯ
SELECT 
    d.name AS department,        -- 5. Выбор и переименование
    COUNT(e.id) AS emp_count     -- 5. Агрегация
FROM employees e                 -- 1. Определение таблицы
JOIN departments d ON e.dept_id = d.id -- 1. Соединение
WHERE e.salary > 50000           -- 2. Фильтрация строк
GROUP BY d.name                  -- 3. Группировка
HAVING COUNT(e.id) > 5          -- 4. Фильтрация групп
ORDER BY emp_count DESC          -- 6. Сортировка
LIMIT 10;                        -- 7. Ограничение вывода

Ответ 18+ 🔞

А, ну вот, опять про SQL и его порядок выполнения! Ебать мои старые костыли, сколько раз уже объяснял, а народ всё путает, как будто впервые видит. Слушай сюда, распиздяй, сейчас разложу по полочкам, чтобы даже мартышлюшка поняла.

Вот пишешь ты запрос, думаешь, что он выполняется сверху вниз, как книжку читаешь. А на самом деле движок базы данных смотрит на это всё и такой: "Э, сабака сука, э бошка думай!". Он делает всё по-своему, хитрая жопа.

Сначала, блядь, FROM и JOIN. Это как прийти в бар — сначала определяешь, откуда вообще будешь пить. Берёшь все таблицы, соединяешь их как бог на душу положит, и получается какой-то промежуточный мега-набор данных, овердохуища строк.

Потом в дело вступает WHERE. Вот тут-то ты и говоришь: "А ну-ка, отсеиваем всё ненужное!". Зарплата меньше пятидесяти тысяч? Нахуй! Дата приёма — позавчера? В пизду! Он отфильтровывает строки, которые тебе не интересны, прямо на месте.

Дальше, если надо, идёт GROUP BY. Это когда ты всех оставшихся чуваков начинаешь сгонять в кучки по отделам, по городам, по чёрту в ступе. Собрал всех айтишников в одну кучку, бухгалтеров — в другую.

Следом за ним — HAVING. А это, блядь, уже не про отдельные строки, а про целые кучи, которые нагруппировали. "А ну-ка, покажите мне только те отделы, где в кучке больше пяти человек!". Остальные — накрылись медным тазом.

И только теперь, ёпта, наступает черёд SELECT! Всё, что осталось, он начинает украшать: считает агрегатные функции (COUNT, SUM), даёт столбцам красивые имена (AS department), вычисляет что-то на лету. До этого момента алиасов типа emp_count просто не существует, они — хуй с горы.

Ну а под конец уже причёсываем результат: ORDER BY сортирует как скажешь, а LIMIT отрезает ровно столько, сколько попросил.

Почему это, блядь, важно? Да потому что постоянно пытаются в условии WHERE использовать алиас из SELECT! А его там, блядь, ещё нет! Доверия ебать ноль к такой логике. WHERE выполняется пятым, а SELECT — только десятым, понимаешь? Алиасы работают только в ORDER BY и HAVING, потому что они идут позже.

Смотри пример, чтобы вообще ни хуя себе не осталось:

-- Ты пишешь вот так (порядок НАПИСАНИЯ)
SELECT 
    d.name AS department,        -- 5. Выбор и переименование (НА САМОМ ДЕЛЕ 5-й шаг)
    COUNT(e.id) AS emp_count     -- 5. Агрегация (НА САМОМ ДЕЛЕ 5-й шаг)
FROM employees e                 -- 1. Определение таблицы (НА САМОМ ДЕЛЕ 1-й шаг)
JOIN departments d ON e.dept_id = d.id -- 1. Соединение (НА САМОМ ДЕЛЕ 1-й шаг)
WHERE e.salary > 50000           -- 2. Фильтрация строк (НА САМОМ ДЕЛЕ 2-й шаг)
GROUP BY d.name                  -- 3. Группировка (НА САМОМ ДЕЛЕ 3-й шаг)
HAVING COUNT(e.id) > 5          -- 4. Фильтрация групп (НА САМОМ ДЕЛЕ 4-й шаг)
ORDER BY emp_count DESC          -- 6. Сортировка (НА САМОМ ДЕЛЕ 6-й шаг)
LIMIT 10;                        -- 7. Ограничение вывода (НА САМОМ ДЕЛЕ 7-й шаг)

Вот и вся магия. Запомни эту цепочку, и будешь понимать, почему запрос не работает, когда пытаешься в WHERE сослаться на emp_count. Потому что в этот момент emp_count — это ещё просто хуй в пальто, а не результат подсчёта.