Итоговые данные
Фильтрующие группы
В дополнение к способности группировать данные с помощью предложения GROUP BY, SQL также позволяет осуществлять фильтрацию — указывать, какие группы должны быть включены в результат, а какие исключены из него. Например, вам может понадобиться список клиентов, которые сделали хотя бы два заказа. Чтобы получить такие данные, необходим фильтр, относящийся к целой группе, а не к отдельным строкам.
Вы уже знаете, как действует предложение WHERE (его мы рассматривали ранее, в разделе, "Фильтрация данных"). Однако в данном случае предложение WHERE использовать нельзя, поскольку фильтры WHERE указывают строки, а не группы. Собственно говоря, WHERE "не знает", что такое группы.
Но тогда что можно использовать вместо предложения WHERE? SQL предлагает другое предложение, подходящее для этих целей: предложение HAVING. Предложение HAVING очень похоже на предложение WHERE. И действительно, все типы выражений в предложении WHERE, с которыми вы уже знакомы, могут быть также использованы с предложением HAVING. Единственная разница состоит в том, что WHERE фильтрует строки, a HAVING — группы.
Предложение HAVING можно использовать со всеми операторами
Вспомним, как фильтруются строки. Посмотрите на следующий пример:
cust_id orders
------------- --------------
1000000001 2
Первые три строки этого оператора SELECT аналогичны оператору, рассмотренному ранее. Последняя строка добавляет к нему предложение HAVING, которое фильтрует эти группы с помощью функции COUNT (*) >= 2 — два или больше заказов.
Как видите, предложение WHERE здесь не работает, поскольку фильтрация основана на итоговом значении группы, а не на значениях указанных строк.
Разница между HAVING и WHERE
А теперь подумаем: возникает ли необходимость в использовании как предложения WHERE, так и предложения HAVING в одном операторе?
Конечно, возникает. Предположим, вы хотите усовершенствовать фильтр предыдущего оператора таким образом, чтобы он возвращал имена всех клиентов, которые сделали два или больше заказов за последние 12 месяцев. Чтобы добиться этого, вы можете добавить предложение WHERE, которое берет во внимание только заказы, сделанные в последние 12 месяцев. Затем вы добавляете предложение HAVING, чтобы отфильтровать только те группы, в которых имеются две или больше строк.
Чтобы лучше разобраться в этом, рассмотрим следующий пример, где перечисляются все поставщики, которые предлагают несколько продуктов по цене 4 и более за единицу:
vend_id num_prods
-------------- ---------------
BRSOl 3
FNGOl 2
Этот пример нуждается в пояснении. Первая строка представляет собой основной оператор SELECT, использующий статистическую функцию, — точно так же, как в предыдущих примерах. Предложение WHERE фильтрует все строки со значениями в столбце prod_price не менее 4. Затем данные группируются по столбцу vend_id, а потом предложение HAVING фильтрует только группы, содержащие не менее двух членов. При отсутствии предложения WHERE была бы получена лишняя строка (поставщик, предлагающий 4 продукта, каждый из которых дешевле 4), как показано ниже.
vend_id num_prods
------------ -------------
BRSOl 3
DLLOl 4
FNGOl 2



