TGViewer
SQL: Реляционные базы данных SQL: Реляционные базы данных @relational_databases · 986 subscribers
Post #124 1.5K
❗️ HAVING в SQL

Многие думают, что оператор HAVING — это просто аналог WHERE, но после GROUP BY. Это упрощение, которое может привести к путанице. Давайте разберём настоящую теорию — шаг за шагом.

Здесь нужно понимать, что SQL-запрос выполняется СУБД не в том порядке, в котором он написан человеком. Это критически важно для понимания HAVING.

❗️ Логический порядок с точки зрения исполнения СУБД (упрощённо):
1. FROM — загрузка данных из таблиц(ы)
2. WHERE — фильтрация отдельных строк
3. GROUP BY — разбиение оставшихся строк на группы
4. Вычисление агрегатных функций (COUNT, SUM, AVG и т.д.) для каждой группы
5. HAVING — фильтрация групп на основе результатов агрегации
6. SELECT — формирование выходных колонок (включая алиасы)
7. ORDER BY, LIMIT, и т.д.

⛔️ Именно потому, что агрегаты появляются только на шаге 4, их нельзя использовать в WHERE — на момент выполнения WHERE (шаг 2) групп ещё не существует!

❗️ HAVING — это условие в SQL, которое фильтрует группы строк после того, как они были объединены с помощью GROUP BY.

❗️ Что такое «группа» в реляционной алгебре?

SQL основан на реляционной алгебре. Оператор GROUP BY трансформирует отношение (таблицу) в множество групп, где каждая группа — это подмножество строк с одинаковым значением ключа группировки.

Пример:
GROUP BY department

Cоздаёт столько групп, сколько уникальных значений в колонке department. Каждая такая группа — новая логическая единица, и к ней можно применять агрегатные функции, которые сводят множество строк к одному значению (например, средняя зарплата в отделе).

❗️ Почему WHERE не может работать с агрегатами?

Потому что WHERE работает на уровне кортежей (строк), а не групп. Он отвечает на вопрос: «Оставить ли эту конкретную строку в результирующем наборе до группировки?». Агрегатные функции, напротив, не определены для одной строки — они требуют множества. Например, AVG(salary) для одной строки — это просто salary, но SQL не позволяет так делать в WHERE, чтобы избежать семантической неоднозначности.

❗️ Когда использовать HAVING?
Используй HAVING, когда твоё условие зависит от результата агрегации по группе.

❗️ Примеры:
➖ «Отделы с более чем 10 сотрудниками» — HAVING COUNT(*) > 10
➖ «Категории товаров, где общая выручка < 1000» — HAVING SUM(price * quantity) < 1000
➖ «Пользователи, сделавшие хотя бы 3 заказа» — HAVING COUNT(order_id) >= 3

❗️ Пример в коде:
Найдём отделы, где средняя зарплата больше 70 000.
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 70000;

Если попытаться написать это через WHERE — получим ошибку:
WHERE AVG(salary) > 70000
-- СУБД заруинила запрос

Потому что на этапе WHERE ещё нет групп, а значит — нет и средней зарплаты по отделу.

❗️ Итого
Используй WHERE, если фильтруешь по конкретным значениям (например, status = 'active').
Используй HAVING, если фильтруешь по результатам агрегации (COUNT(*) > 5, AVG(price) < 100).

#SQL #HAVING

📱 Подписаться на канал
💻 Курс автора по SQL DDL
🌎 Мой ИТ-стартап
  • 🔥 33
  • 💯 10
  • 👾 6
  • 🤔 1
More from @relational_databases
  1. Oct 4, 2026❗️ Как найти дубли и оставить последнюю запись Одна из самых частых задач аналитика, это п…
  2. Jun 28, 2026Краткий справочник по типам данных к посту
  3. Jun 28, 2026👩‍💻 Типы данных в PostgreSQL: как они устроены и почему их выбор имеет значение Одна из…
  4. May 3, 2026Всем привет)) Я вернулся, так что с этой недели будут новые посты, будем воскрешать канал.…
  5. Dec 31, 2025🥳Всех с наступающим! Решил подвести, итоги года для канала. Создавая его в феврале, я даж…
  6. Nov 23, 20250️⃣ NULL в SQL - не "ничего", а "неизвестно" Когда вы видите NULL в таблице, интуиция подс…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →