Ответ
Ключевое отличие — этап выполнения запроса, на котором применяется фильтрация.
- WHERE фильтрует отдельные строки до группировки (
GROUP BY). - HAVING фильтрует агрегированные результаты (группы) после группировки.
Порядок выполнения и синтаксис:
SELECT department, AVG(salary) as avg_sal -- 5. Выбор полей
FROM employees -- 1. Источник данных
WHERE hire_date > '2020-01-01' -- 2. Фильтрация СТРОК (до группировки)
GROUP BY department -- 3. Группировка
HAVING AVG(salary) > 70000 -- 4. Фильтрация ГРУПП (после группировки)
ORDER BY avg_sal DESC; -- 6. Сортировка
Правила использования:
- WHERE не может содержать агрегатные функции (
SUM,COUNT,AVG). - HAVING часто используется с агрегатными функциями для фильтрации групп.
- WHERE выполняется раньше, уменьшая объем данных для группировки, что повышает производительность.
Пример для понимания:
-- НЕВЕРНО: Агрегатная функция в WHERE
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5 -- Ошибка!
GROUP BY department;
-- ВЕРНО: Агрегатная функция в HAVING
SELECT department, COUNT(*) as emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5; -- Фильтруем группы, где количество сотрудников > 5 Ответ 18+ 🔞
А, ну это же классика, блядь! Вечный вопрос, который всех новичков в SQL нахуй путает. Слушай сюда, я тебе на пальцах, как Герасим Муму, объясню, только без утопления, окей?
Короче, представь, что ты начальник цеха, а employees — это твои работяги.
WHERE — это ты стоишь на входе в цех и отсеиваешь мудаков до того, как они зайдут. "Ты, Вася, опоздал на неделю — нахуй отсюда! Ты, Маша, ещё на испытательном — проходи, работай". Это фильтрация отдельных строк, блядь, поштучно. Агрегатных функций тут быть не может, потому что ты ещё не знаешь, сколько их там в итоге будет и кто сколько заработал. Ты просто по одному смотришь.
WHERE hire_date > '2020-01-01' -- "Все, кто пришёл после 2020-го, заходите. Остальные — пошли нахуй!"
Потом эти отфильтрованные работяги заходят в цех, и ты их группируешь (GROUP BY) по отделам. Собрал всех сварщиков в одну кучу, токарей — в другую.
А вот HAVING — это ты уже после группировки смотришь на итоги по отделам. Ты не к каждому работяге лезешь, а смотришь на сводку: "Средняя зарплата по отделу", "Количество человек".
И вот тут ты фильтруешь уже целые группы, ёпта!
HAVING AVG(salary) > 70000 -- "Отдел сварщиков, у вас средняя зп 50к? Нахуй такой отдел, расформировать! Токари, у вас 80к? Молодцы, премия!"
Главное правило, которое вбить себе в башку, как гвоздь:
- WHERE — фильтрует строки, ДО группировки. С агрегатными функциями (
COUNT,AVG) — НИКОГДА. - HAVING — фильтрует группы, ПОСЛЕ группировки. Чаще всего ИМЕННО С агрегатными функциями.
Вот смотри, как дурак пытается в WHERE агрегатную функцию сунуть — получается пиздец и ошибка:
-- НЕВЕРНО (Типичная мудацкая попытка):
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5 -- Ошибка! SQL орет: "Какой нахуй COUNT, я ещё даже не сгруппировал никого, ты о чём?"
GROUP BY department;
А вот как умный человек делает — фильтрует результат группировки:
-- ВЕРНО (Работает, как швейцарские часы, блядь):
SELECT department, COUNT(*) as emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5; -- "Показывай только те отделы, где больше 5 человек. Остальные — мелочь, нихуя не интересны".
Итог, чтобы не ебать мозг: Сначала WHERE отсекает лишних поодиночке (эффективно, меньше данных грузить), потом GROUP BY кучкует, а HAVING уже отшивает целые кучи, которые не прошли по твоим агрегатным критериям. Всё, вопрос закрыт, можно идти пить чай.