Sql Scholl
Распечатать страницу
Перейти на главную Карта сайта Отправить сообщение

Итоговые данные

Фильтрующие группы

        В дополнение к способности группировать данные с помощью предложения GROUP BY, SQL также позволяет осуществлять фильтрацию — указывать, какие группы должны быть включены в результат, а какие исключены из него. Например, вам может понадобиться список клиентов, которые сделали хотя бы два заказа. Чтобы получить такие данные, необходим фильтр, относящийся к целой группе, а не к отдельным строкам.

       Вы уже знаете, как действует предложение WHERE (его мы рассматривали ранее, в разделе, "Фильтрация данных"). Однако в данном случае предложение WHERE использовать нельзя, поскольку фильтры WHERE указывают строки, а не группы. Собственно говоря, WHERE "не знает", что такое группы.

       Но тогда что можно использовать вместо предложения WHERE? SQL предлагает другое предложение, подходящее для этих целей: предложение HAVING. Предложение HAVING очень похоже на предложение WHERE. И действительно, все типы выражений в предложении WHERE, с которыми вы уже знакомы, могут быть также использованы с предложением HAVING. Единственная разница состоит в том, что WHERE фильтрует строки, a HAVING — группы.  

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

Из предидущих вы знаете, как можно применять предложение WHERE (включая использование метасимволов и логических операций). Все эти методы и опции могут быть применены и по отношению к HAVING. Синтаксис такой же, отличаются только ключевые слова.

     Вспомним, как фильтруются строки. Посмотрите на следующий пример:

SELECT cust_id, COUNT(*) AS orders FROM Orders GROUP BY cust_id HAVING COUNT(*) >= 2;


cust_id        orders 
-------------  --------------
1000000001     2

      Первые три строки этого оператора SELECT аналогичны оператору, рассмотренному ранее. Последняя строка добавляет к нему предложение HAVING, которое фильтрует эти группы с помощью функции COUNT (*) >= 2 — два или больше заказов.

      Как видите, предложение WHERE здесь не работает, поскольку фильтрация основана на итоговом значении группы, а не на значениях указанных строк.

Разница между HAVING и WHERE

Вот как это можно рассматривать: where фильтрует до того, как данные будут сгруппированы, a having фильтрует после того, как данные были сгруппированы. Это— важное различие; строки, которые были выброшены по предложению where, не будут включены в группу, иначе это могло бы изменить вычисляемые значения, которые, в свою очередь, могли бы повлиять на фильтрацию групп в предложении having.

      А теперь подумаем: возникает ли необходимость в использовании как предложения WHERE, так и предложения HAVING в одном операторе?

      Конечно, возникает. Предположим, вы хотите усовершенствовать фильтр предыдущего оператора таким образом, чтобы он возвращал имена всех клиентов, которые сделали два или больше заказов за последние 12 месяцев. Чтобы добиться этого, вы можете добавить предложение WHERE, которое берет во внимание только заказы, сделанные в последние 12 месяцев. Затем вы добавляете предложение HAVING, чтобы отфильтровать только те группы, в которых имеются две или больше строк.

      Чтобы лучше разобраться в этом, рассмотрим следующий пример, где перечисляются все поставщики, которые предлагают несколько продуктов по цене 4 и более за единицу:

SELECT vend_id, COUNT(*) AS num_prods FROM Products WHERE prod_price >= 4 GROUP BY vend_id HAVING COUNT(*) >= 2;



vend_id          num_prods 
--------------   ---------------
BRSOl            3
FNGOl            2

       Этот пример нуждается в пояснении. Первая строка представляет собой основной оператор SELECT, использующий статистическую функцию, — точно так же, как в предыдущих примерах. Предложение WHERE фильтрует все строки со значениями в столбце prod_price не менее 4. Затем данные группируются по столбцу vend_id, а потом предложение HAVING фильтрует только группы, содержащие не менее двух членов. При отсутствии предложения WHERE была бы получена лишняя строка (поставщик, предлагающий 4 продукта, каждый из которых дешевле 4), как показано ниже.

SELECT vend_id, COUNT(*) AS num_prods FROM Products GROUP BY vend_id HAVING COUNT(*) >= 2;



vend_id         num_prods 
------------    -------------
BRSOl           3
DLLOl           4
FNGOl           2

 

Использование предложений HAVING И WHERE

Предложение having так похоже на предложение where, что в большинстве СУБД оно трактуется точно так же, если только не указано никакое предложение group BY. И все же вы должны знать, что между ними существует разница. Используйте предложение having только вместе с предложениями group by, a предложение where — для стандартной фильтрации на уровне строк.