1.3Kпросмотров
3 октября 2025 г.
📷 ФотоScore: 1.4K
❗️ 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
🌎 Мой ИТ-стартап