HAVING
Так же, как и предложение WHERE ограничивает строки в наборе данных, теми которые удовлетворяют условию поиска, с той разницей, что предложение HAVING накладывает ограничения на агрегированные строки сгруппированного набора.Предложение HAVING не является обязательным и может быть использовано только в сочетании с предложением GROUP BY.
Условие(я) в предложении HAVING может ссылаться на:
-
Любой агрегированный столбец в списке выбора
SELECT. Это наиболее широко используемый случай; -
Любое агрегированное выражение, которое не находится в списке выбора
SELECT, но разрешено в контексте запроса. Иногда это полезно; -
Любой столбец в списке
GROUP BY. Однако более эффективно фильтровать не агрегированные данные на более ранней стадии в предложенииWHERE; -
Любое выражение, значение которого не зависит от содержимого набора данных (например, константа или контекстная переменная). Это допустимо, но совершенно бессмысленно, потому что такое условие, не имеющее никакого отношения к самому набору данных, либо подавит весь набор, либо оставит его не тронутым.
Предложение HAVING не может содержать:
-
Не агрегированные выражения столбца, которые не находятся в списке GROUP BY;
-
Позицию столбца. Целое число в предложении
HAVING– просто целое число; -
Псевдонимы столбца –- даже если они появляются в предложении
GROUP BY.
Примеры
Перестроим наши ранние примеры.Мы можем использовать предложение HAVING для исключения малых групп студентов:
SELECT
class,
COUNT(*) AS num_boys,
AVG(age) AS boys_avg_age
FROM students
WHERE sex = 'M'
GROUP BY class
HAVING COUNT(*) >= 5
Выберем только группы, которые имеют минимальный разброс по возрасту 1.2 года:
SELECT
class,
COUNT(*) AS num_boys,
AVG(age) AS boys_avg_age
FROM students
WHERE sex = 'M'
GROUP BY class
HAVING MAX(age) - MIN(age) > 1.2
Обратите внимание, что если вас действительно интересует эта информация, то неплохо бы включить в список выбора min(age) и max(age) или выражение max(age) – min(age).
Следующий запрос отбирает только учеников 3 класса:
SELECT
class,
COUNT(*) AS num_boys,
AVG(age) AS boys_avg_age
FROM students
WHERE sex = 'M'
GROUP BY class
HAVING class STARTING WITH '3'
Однако гораздо лучше переместить это условие в предложение WHERE:
SELECT
class,
COUNT(*) AS num_boys,
AVG(age) AS boys_avg_age
FROM students
WHERE sex = 'M' AND class STARTING WITH '3'
GROUP BY class