В чем разница между WHERE и HAVING в SQL?

Ответ

Ключевое отличие — этап выполнения запроса, на котором применяется фильтрация.

  • 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. Сортировка

Правила использования:

  1. WHERE не может содержать агрегатные функции (SUM, COUNT, AVG).
  2. HAVING часто используется с агрегатными функциями для фильтрации групп.
  3. 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 уже отшивает целые кучи, которые не прошли по твоим агрегатным критериям. Всё, вопрос закрыт, можно идти пить чай.