Работает ли SQL WHERE с агрегатными функциями

Ответ

Нет, WHERE не работает напрямую с агрегатными функциями (SUM, COUNT, AVG и т.д.). Для фильтрации по агрегатным функциям нужно использовать HAVING после GROUP BY.

Пример:

SELECT department, AVG(salary) 
FROM employees 
GROUP BY department 
HAVING AVG(salary) > 50000;

Разница:

  • WHERE фильтрует строки до группировки
  • HAVING фильтрует после группировки и агрегации

Можно использовать оба в одном запросе:

SELECT department, AVG(salary) 
FROM employees 
WHERE hire_date > '2020-01-01'
GROUP BY department 
HAVING AVG(salary) > 50000;

Ответ 18+ 🔞

Да ты глянь, какой прикол! В SQL есть такая хитрая жопа с WHERE и HAVING, которая народ в ступор вгоняет постоянно. Слушай сюда, я тебе на пальцах объясню, а то ты, я смотрю, уже волнение ебать чувствую.

Вот представь: у тебя таблица с работягами, employees. Ты хочешь посчитать среднюю зарплату по отделам. Делаешь GROUP BY department и AVG(salary). И тут тебе в голову приходит гениальная мысль: «А дай-ка я оставлю только те отделы, где средняя зарплата больше 50к!» И ты, естественно, пишешь:

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000  -- Вот тут-то тебя и накроет медным тазом!
GROUP BY department;

И бац! Сервер тебе такой: «Э, сабака сука! Нельзя агрегатную функцию в WHERE использовать!» И он прав, блядь. Потому что WHERE работает как фильтр ДО того, как данные сгруппируют и посчитают среднее. Он смотрит на каждую строчку по отдельности и спрашивает: «Ну-ка, покажи мне свою среднюю зарплату, строка номер 1». А у строки номер 1 своей средней зарплаты нет, она же одна! Это же AVG по всем считает. Вот и получается пиздопроебибна.

Так какого хуя делать-то?

А делать надо так. Сначала ты всё сгруппировал и посчитал (GROUP BY). Получились готовые агрегированные результаты по отделам. И вот только после этого ты можешь их отфильтровать. Для этого и придумали HAVING. Это как WHERE, но для сгруппированных данных.

Правильный запрос выглядит так:

SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;  -- Всё, теперь работает! Фильтруем готовые результаты групп.

А можно ли их вместе использовать? Да похуй, конечно можно! Это вообще мощнейшая комбинация.

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

SELECT department, AVG(salary)
FROM employees
WHERE hire_date > '2020-01-01'  -- Сначала отфильтруем строки: только новенькие.
GROUP BY department              -- Потом сгруппируем этих новеньких по отделам.
HAVING AVG(salary) > 50000;     -- И наконец отфильтруем сами отделы по средней ЗП.

Кратко и по делу, чтобы в душу мать въелось:

  • WHERE — фильтрует строчки ДО группировки. Тут агрегатные функции (SUM, AVG) — хуй с горы.
  • HAVING — фильтрует группы ПОСЛЕ группировки. Тут как раз место для агрегатных функций.

Запомни эту разницу, и удивление пиздец у интервьюеров будет, когда ты не облажаешься на этом классическом вопросе.