Предложение HAVING
Если предложение WHERE определяет предикат для фильтрации строк, то предложение HAVING применяется после группировки для определения аналогичного предиката, фильтрующего группы по значениям агрегатных функций. Это предложение необходимо для проверки значений, которые получены с помощью агрегатной функции не из отдельных строк источника записей, определенного в предложении FROM, а из групп таких строк. Поэтому такая проверка не может содержаться в предложении WHERE.
Пример 5.5.5
SELECT model,
COUNT(model) AS Qty_model,
AVG(price) AS Avg_price
FROM PC
GROUP BY model
HAVING AVG(price) < 800;
[[ column ]] |
---|
[[ value ]] |
В результате выполнения запроса получим:
model | Qty_model | Avg_price |
---|---|---|
1232 | 4 | 425 |
1260 | 1 | 350 |
Заметим, что в предложении HAVING нельзя использовать псевдоним (Avg_price), используемый для именования значений агрегатной функции в предложении SELECT. Дело в том, что предложение SELECT, формирующее выходной набор запроса, выполняется предпоследним перед предложением ORDER BY. Ниже приведен порядок обработки предложений в операторе SELECT:
- FROM
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
Этот порядок не соответствует синтаксическому порядку общего представления оператора SELECT, который ближе к естественному языку:
SELECT [DISTINCT | ALL]{*
| [<выражение для столбца> [[AS] <псевдоним>]] [,…]}
FROM <имя таблицы> [[AS] <псевдоним>] [,…]
[WHERE <предикат>]
[[GROUP BY <список столбцов>]
[HAVING <условие на агрегатные значения>] ]
[ORDER BY <список столбцов>]
Следует отметить, что предложение HAVING может использоваться и без предложения GROUP BY. При отсутствии предложения GROUP BY агрегатные функции применяются ко всему выходному набору строк запроса, т.е. в результате мы получим всего одну строку, если выходной набор не пуст.
Таким образом, если условие на агрегатные значения в предложение HAVING будет истинным, то эта строка будет выводиться, в противном случае мы не получим ни одной строки. Рассмотрим такой пример.
Пример 5.5.6
Решение этой задачи дает следующий запрос:
SELECT MIN(price) AS min_price,
MAX(price) AS max_price,
AVG(price) avg_price
FROM PC;
[[ column ]] |
---|
[[ value ]] |
min_price | max_price | avg_price |
---|---|---|
350 | 980 | 675 |
Если же мы добавим в условие ограничение, скажем, на среднюю цену:
SELECT MIN(price) AS min_price,
MAX(price) AS max_price,
AVG(price) avg_price
FROM PC
HAVING AVG(price) <= 600;
[[ column ]] |
---|
[[ value ]] |
Рекомендуемые упражнения: 15, 20, 28, 37, 40, 57, 63, 67, 68, 70, 72, 76, 81, 82, 85, 87, 89, 102, 114, 126, 129