HAVING. Условный оператор для собирательных функций

Оператор HAVING

HAVING используется вместо оператора WHERE, т.к. WHERE не может быть применен совместно с собирательными функциями (COUNT()MIN()MAX()SUM()AVG()).

Синтаксис HAVING

SELECT column1, column2, ... , columnN FROM table_name WHERE condition
GROUP BY column1, column2, ... , columnN HAVING condition

Пример использования оператора HAVING

Рассмотрим пример использования оператора HAVING на таблице books из базы данных для интернет-магазина Bookstore.

Выведем все записи таблицы books.

mysql> SELECT id, title, author, price, amount FROM books;
+----+---------------------------+--------------------+--------+--------+
| id | title                     | author             | price  | amount |
+----+---------------------------+--------------------+--------+--------+
|  1 | Дубровский                | Александр Пушкин   | 230.00 |     20 |
|  2 | Нос                       | Николай Гоголь     | 255.20 |      7 |
|  3 | Мастер и Маргарита        | Михаил Булгаков    | 263.00 |      8 |
|  4 | Мёртвые души              | Николай Гоголь     | 230.00 |      3 |
|  5 | Преступление и наказание  | Фёдор Достоевский  | 230.00 |      3 |
|  6 | Война и мир               | Лев Толстой        | 346.00 |      1 |
|  7 | Анна Каренина             | Лев Толстой        | 346.00 |      0 |
|  8 | Отцы и дети               | Иван Тургенев      | 371.00 |      3 |
|  9 | Собачье сердце            | Михаил Булгаков    | 232.00 |      0 |
| 10 | Театральный роман         | Михаил Булгаков    | 212.00 |      8 |
+----+---------------------------+--------------------+--------+--------+
10 rows in set (0.00 sec)

Допустим стоит задача узнать, книг какого автора, у нас имеется в наличии меньше всего.

Для этого нам понадобится подсчитать все записи, которые имеют одного и того же автора и сгруппировать их по колонке author. 

mysql> SELECT COUNT(id) AS 'Число книг', author FROM books
    -> GROUP BY author HAVING COUNT(id) <= 1
+-------------+-------------------------------+
| Число книг  | author                        |
+-------------+-------------------------------+
|           1 | Александр Пушкин              |
|           1 | Иван Тургенев                 |
|           1 | Фёдор Достоевский             |
+-------------+-------------------------------+
1 row in set (0.00 sec)

В результате выполнения запроса увидим, что мы имеем только по одной книге за авторством Александра Пушкина, Ивана Тургенева и Фёдора Достоевского.

Использование HAVING с объединением LEFT JOIN

В данном примере узнаем кто из работников интернет-магазина обработал больше 3 заказов.

Выведем содержимое таблиц employees и orders для ознакомления.

mysql> SELECT id, first_name, last_name, position FROM employees;
+----+------------+-----------+------------------+
| id | first_name | last_name | position         |
+----+------------+-----------+------------------+
|  1 | Абросим    | Сумароков | Ген. Директор    |
|  2 | Александр  | Суматохин | Старший продавец |
|  3 | Петр       | Стропин   | Продавец         |
|  4 | Фёдор      | Телецкий  | Кладовщик        |
|  5 | Аркадий    | Прошин    | Продавец         |
+----+------------+-----------+------------------+
5 rows in set (0.00 sec)

mysql> SELECT id, employee_id, status, order_date FROM orders;
+----+-------------+------------------+---------------------+
| id | employee_id | status           | order_date          |
+----+-------------+------------------+---------------------+
|  3 |           3 | Готов к отправке | 2019-01-05 04:55:58 |
|  6 |           5 | Готов к отправке | 2019-01-15 14:56:12 |
|  7 |           5 | Завершен         | 2019-01-11 20:59:40 |
|  9 |           3 | Обрабатывается   | 2018-12-22 21:16:16 |
| 10 |           3 | Готов к отправке | 2018-12-24 04:28:54 |
| 14 |           2 | Ждет оплаты      | 2018-12-30 15:42:18 |
| 15 |           3 | Новый            | 2018-12-29 02:11:21 |
| 16 |           3 | Готов к отправке | 2018-12-31 20:56:25 |
| 20 |           2 | Ждет оплаты      | 2019-01-19 11:14:33 |
| 21 |           5 | Завершен         | 2019-01-14 02:30:04 |
+----+-------------+------------------+---------------------+
10 rows in set (0.00 sec)

Можно заметить что таблицы orders и employees связаны колонками orders.employee_id и employees.id, а значит мы можем узнать все данные о работнике, который обработал тот или иной заказ.

Объединим обе таблицы и выясним, кто из работников обработал больше 3 заказов.

mysql> SELECT COUNT(orders.id) AS 'Число заказов',
    -> employees.first_name, employees.last_name, position
    -> FROM employees
    -> LEFT JOIN orders ON orders.employee_id = employees.id
    -> GROUP BY employees.id HAVING COUNT(employees.id) > 3;
+---------------+------------+-----------+----------+
| Число заказов | first_name | last_name | position |
+---------------+------------+-----------+----------+
|             5 | Петр       | Стропин   | Продавец |
+---------------+------------+-----------+----------+
1 row in set (0.00 sec)

Только работник по имени Петр Стропин обработал больше 3 заказов среди всех своих коллег.