← Назад к вопросам

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

1.0 Junior🔥 201 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Разница между WHERE и HAVING в базах данных

WHERE и HAVING - это оба условные операторы в SQL, но они используются в разных контекстах: WHERE фильтрует строки ДО агрегации, HAVING фильтрует результаты ПОСЛЕ агрегации.

WHERE: Фильтр строк ДО агрегации

WHERE применяется к исходным данным ДО выполнения GROUP BY и агрегирующих функций.

SELECT order_id, customer_id, total
FROM orders
WHERE total > 1000;
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByTotalGreaterThan(BigDecimal total);
}

HAVING: Фильтр групп ПОСЛЕ агрегации

HAVING применяется к результатам GROUP BY и агрегирующих функций.

SELECT customer_id, COUNT(*) as order_count, SUM(total) as total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(total) > 10000;

Пошаговое выполнение SQL запроса

ШАГ 1: WHERE - фильтруем строки (было 10,000) → 8,000 строк
ШАГ 2: GROUP BY - группируем по customer_id → 500 групп  
ШАГ 3: Агрегирующие функции (COUNT, SUM) → вычисляем для каждой группы
ШАГ 4: HAVING - фильтруем группы по условию → 350 групп
ШАГ 5: ORDER BY - сортируем результаты

Сравнительная таблица

АспектWHEREHAVING
Когда применяетсяДО GROUP BYПОСЛЕ GROUP BY
На что действуетНа строки таблицыНа результаты агрегации
Агрегирующие функцииНельзя использоватьМожно использовать
ПроизводительностьБыстроМедленнее

Практические примеры

Пример 1: Найти дорогие товары дорогих категорий

-- НЕПРАВИЛЬНО (ошибка)
SELECT product_id, category, price
FROM products
WHERE AVG(price) > 100
GROUP BY category;

-- ПРАВИЛЬНО
SELECT category, AVG(price) as avg_price
FROM products
WHERE price > 50
GROUP BY category
HAVING AVG(price) > 100;

Пример 2: Активные пользователи

@Query("SELECT c.userId, COUNT(c) FROM Comment c WHERE c.createdAt >= :date GROUP BY c.userId HAVING COUNT(c) > 10")
List<Object[]> findActiveUsers(LocalDateTime date);

Пример 3: Самые популярные теги

SELECT t.name, COUNT(*) as usage_count
FROM tags t
LEFT JOIN post_tags pt ON t.id = pt.tag_id
WHERE pt.post_id IS NOT NULL
GROUP BY t.id, t.name
HAVING COUNT(*) > 100
ORDER BY usage_count DESC;

Частые ошибки

Ошибка 1: Использование агрегирующих функций в WHERE

-- НЕПРАВИЛЬНО
SELECT customer_id, SUM(total)
FROM orders
WHERE SUM(total) > 1000
GROUP BY customer_id;

-- ПРАВИЛЬНО
SELECT customer_id, SUM(total) as total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(total) > 1000;

Ошибка 2: WHERE после GROUP BY

-- НЕПРАВИЛЬНО
SELECT category, AVG(price)
FROM products
GROUP BY category
WHERE AVG(price) > 100;

-- ПРАВИЛЬНО
SELECT category, AVG(price) as avg_price
FROM products
GROUP BY category
HAVING AVG(price) > 100;

Когда использовать WHERE vs HAVING

WHERE: фильтруем исходные данные, условия на отдельные строки

  • customer_id = 5
  • price > 100
  • order_date >= '2023-01-01'

HAVING: фильтруем результаты агрегации, условия на группы

  • COUNT(*) > 10
  • SUM(total) > 5000
  • AVG(price) > 100

Производительность

-- МЕДЛЕННО (агрегирует все, потом фильтрует)
SELECT category, COUNT(*)
FROM products
GROUP BY category
HAVING COUNT(*) > 10;

-- БЫСТРО (фильтрует, потом агрегирует только нужные)
SELECT category, COUNT(*)
FROM products
WHERE price > 100
GROUP BY category
HAVING COUNT(*) > 10;

Заключение

WHERE фильтрует исходные данные ДО GROUP BY (на строки), HAVING фильтрует результаты ПОСЛЕ GROUP BY (на группы). Обе часто используются вместе: WHERE оптимизирует производительность, HAVING фильтрует результаты агрегации.