В дополнение к способности группировать данные с помощью предложения GROUP BY, SQL также позволяет осуществлять фильтрацию — указывать, какие группы должны быть включены в результат, а какие исключены из него. Например, вам может понадобиться список клиентов, которые сделали хотя бы два заказа. Чтобы получить такие данные, необходим фильтр, относящийся к целой группе, а не к отдельным строкам.
В данном случае предложение WHERE использовать нельзя, поскольку фильтры WHERE указывают строки, а не группы. Собственно говоря, WHERE "не знает", что такое группы.
Но тогда что можно использовать вместо предложения WHERE? SQL предлагает другое предложение, подходящее для этих целей: предложение HAVING. Предложение HAVING очень похоже на предложение WHERE. И действительно, все типы выражений в предложении WHERE могут быть также использованы с предложением HAVING. Единственная разница состоит в том, что WHERE фильтрует строки, a HAVING — группы.
Пример:
Нужно найти страницы с одинаковыми адресами, как выглядит часть таблицы (таблица test):
| id | name | url |
|---|---|---|
| 1 | Главная | / |
| 2 | Раздел | /razdel |
| 3 | Новость | /news |
| 4 | Еще один раздел | /razdel |
Теперь напишем запрос который выведит нужные записи:
select `url` from `test` group by `url` having count(*)>=2
Данный запрос группирует все записи по полю url и выводит те значения поля url которые встречаются 2 или более раз.
Результат будет:
| url |
|---|
| /razdel |
Как видите, предложение WHERE здесь не работает, поскольку фильтрация основана на итоговом значении группы, а не на значениях указанных строк.
Вот как это можно рассматривать: WHERE фильтрует до того, как данные будут сгруппированы, a HAVING фильтрует после того, как данные были сгруппированы. Это— важное различие; строки, которые были выброшены по предложению WHERE, не будут включены в группу, иначе это могло бы изменить вычисляемые значения, которые, в свою очередь, могли бы повлиять на фильтрацию групп в предложении HAVING.
Статья написана на основе главы "Фильтрующие группы" из книги Освой самостоятельно SQL.