HAVING: условие за групите
Накратко: HAVING филтрира групите след GROUP BY с условие върху агрегатна функция, например SUM(total) > 100, което WHERE не може, защото работи преди групирането.
Проблем
Картата за лоялност
Магазинът пуска карта за лоялност: получават я клиентите с повече от 3 поръчки. Знаеш как да преброиш поръчките на всеки клиент с GROUP BY customer_id. Излизат 18 реда. Как да оставиш само тези с повече от 3?
WHERE не става: той гледа отделните поръчки, а броят е на целия клиент.
Идеята
HAVING
HAVING е условие за групите. Пише се след GROUP BY и в него може да има обобщение:
Четирима клиенти. Групите се правят, броят се смята за всяка, а HAVING оставя само групите, за които условието е вярно.
Пробвай
Големите поръчки
За безплатната доставка ни трябват поръчките за над 30 €. Полето показва стойността на всяка поръчка. Остави само тези над 30 €.
Решение
SELECT order_id, SUM(quantity * unit_price) AS total
FROM order_items
GROUP BY order_id
HAVING SUM(quantity * unit_price) > 30;HAVING SUM(quantity * unit_price) > 30. 25 от 60-те поръчки. SQLite приема и HAVING total > 30 с псевдонима, но не всяка база го прави. Това е темата на следващия урок.
Виж го
SUM в WHERE
Първият опит на почти всеки е със WHERE. Пусни го:
SQLite спира с „misuse of aggregate“: обобщение на място, където не му е мястото. В WHERE базата гледа редовете един по един. Групи още няма, няма и какво да събира.
Идеята
WHERE и HAVING заедно
Двете не си пречат, а работят на различно място:
WHEREфилтрира редовете преди групите;HAVINGфилтрира групите след тях.
Картата за лоялност без отказаните поръчки:
Клиент 7 отпадна. Той има 4 поръчки, но една е отказана. WHERE я махна, преди да се направят групите, и в неговата група останаха 3.
Условие, което гледа отделния ред (status, дата, цена), пиши в WHERE. То намалява редовете, които базата трябва да групира. В HAVING остави само условията върху обобщения.
Пробвай
Само по веднъж
Маркетингът иска да пише на клиентите, които през 2026 г. са поръчали точно веднъж. Броят се всички поръчки, и отказаните. Покажи customer_id и броя на поръчките им от 2026 г.
Решение
SELECT customer_id, COUNT(*)
FROM orders
WHERE ordered_at >= '2026-01-01'
GROUP BY customer_id
HAVING COUNT(*) = 1;WHERE ordered_at >= '2026-01-01', после GROUP BY customer_id и HAVING COUNT(*) = 1. Шестима клиенти. Тези, които не са поръчвали нищо през 2026 г., ги няма: те нямат редове, а значи и група. За тях ще трябва JOIN.
Упражнение
Две справки
1. Доставчиците дават отстъпка за продуктите, от които продаваме много. Кои продукти са продадени в поне 15 бройки?
Покажи product_id и продадените бройки на продуктите с поне 15 продадени бройки.
Решение
SELECT product_id, SUM(quantity)
FROM order_items
GROUP BY product_id
HAVING SUM(quantity) >= 15;GROUP BY product_id HAVING SUM(quantity) >= 15. Десет продукта. „Поне 15“ значи, че и 15 влиза, затова е >=.
2. През кои месеци е имало поне 6 поръчки? Там ще трябват повече хора в склада.
Покажи месеца (година-месец) и броя на поръчките за месеците с поне 6 поръчки.
Решение
SELECT strftime('%Y-%m', ordered_at) AS month, COUNT(*)
FROM orders
GROUP BY strftime('%Y-%m', ordered_at)
HAVING COUNT(*) >= 6;GROUP BY strftime('%Y-%m', ordered_at) HAVING COUNT(*) >= 6. Четири месеца: септември и октомври 2025 г., май и септември 2026 г. Най-натоварен е октомври 2025 г. с 9 поръчки.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Сметки в заявката · Функции за дати · Агрегатни функции: COUNT, SUM, AVG · GROUP BY: отчет по групи
- Продължава в: Редът на изпълнение на заявката · Видове връзки: 1:1, 1:N, M:N · Естествен ключ и денормализация · Документни бази
- Задачи по темата: Обобщаване