Агрегатные функции (Transact-SQL)
Агрегатная функция выполняет вычисление на наборе значений и возвращает одиночное значение. Агрегатные функции, за исключением COUNT(*) , не учитывают значения NULL. Агрегатные функции часто используются в выражении GROUP BY инструкции SELECT.
Все агрегатные функции являются детерминированными. Другими словами, агрегатные функции возвращают одну и ту же величину при каждом их вызове на одном и том же наборе входных значений. Дополнительные сведения о детерминированности функций см. в статье Детерминированные и недетерминированные функции. Предложение OVER может следовать за всеми агрегатными функциями, кроме STRING_AGG, GROUPING или GROUPING_ID.
Агрегатные функции можно использовать в качестве выражений только в следующих случаях.
- Список выбора инструкции SELECT (вложенный или внешний запрос).
- Предложение HAVING.
Transact-SQL предоставляет следующие агрегатные функции:
Какой функции нет в sql having
Для группировки данных в T-SQL применяются операторы GROUP BY и HAVING , для использования которых применяется следующий формальный синтаксис:
SELECT столбцы FROM таблица [WHERE условие_фильтрации_строк] [GROUP BY столбцы_для_группировки] [HAVING условие_фильтрации_групп] [ORDER BY столбцы_для_сортировки]
GROUP BY
Оператор GROUP BY определяет, как строки будут группироваться.
Например, сгруппируем товары по производителю
SELECT Manufacturer, COUNT(*) AS ModelsCount FROM Products GROUP BY Manufacturer
Первый столбец в выражении SELECT — Manufacturer представляет название группы, а второй столбец — ModelsCount представляет результат функции Count, которая вычисляет количество строк в группе.

Стоит учитывать, что любой столбец, который используется в выражении SELECT (не считая столбцов, которые хранят результат агрегатных функций), должны быть указаны после оператора GROUP BY. Так, например, в случае выше столбец Manufacturer указан и в выражении SELECT, и в выражении GROUP BY.
И если в выражении SELECT производится выборка по одному или нескольким столбцам и также используются агрегатные функции, то необходимо использовать выражение GROUP BY. Так, следующий пример работать не будет, так как он не содержит выражение группировки:
SELECT Manufacturer, COUNT(*) AS ModelsCount FROM Products
Другой пример, добавим группировку по количеству товаров:
SELECT Manufacturer, ProductCount, COUNT(*) AS ModelsCount FROM Products GROUP BY Manufacturer, ProductCount
Оператор GROUP BY может выполнять группировку по множеству столбцов.
Если столбец, по которому производится группировка, содержит значение NULL, то строки со значением NULL составят отдельную группу.
Следует учитывать, что выражение GROUP BY должно идти после выражения WHERE , но до выражения ORDER BY :
SELECT Manufacturer, COUNT(*) AS ModelsCount FROM Products WHERE Price > 30000 GROUP BY Manufacturer ORDER BY ModelsCount DESC

Фильтрация групп. HAVING
Оператор HAVING определяет, какие группы будут включены в выходной результат, то есть выполняет фильтрацию групп.
Применение HAVING во многом аналогично применению WHERE. Только есть WHERE применяется к фильтрации строк, то HAVING используется для фильтрации групп.
Например, найдем все группы товаров по производителям, для которых определено более 1 модели:
SELECT Manufacturer, COUNT(*) AS ModelsCount FROM Products GROUP BY Manufacturer HAVING COUNT(*) > 1

При этом в одной команде мы можем использовать выражения WHERE и HAVING:
SELECT Manufacturer, COUNT(*) AS ModelsCount FROM Products WHERE Price * ProductCount > 80000 GROUP BY Manufacturer HAVING COUNT(*) > 1
То есть в данном случае сначала фильтруются строки: выбираются те товары, общая стоимость которых больше 80000. Затем выбранные товары группируются по производителям. И далее фильтруются сами группы — выбираются те группы, которые содержат больше 1 модели.
Если при этом необходимо провести сортировку, то выражение ORDER BY идет после выражения HAVING:
SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS Units FROM Products WHERE Price * ProductCount > 80000 GROUP BY Manufacturer HAVING SUM(ProductCount) > 2 ORDER BY Units DESC
В данном случае группировка идет по производителям, и также выбирается количество моделей для каждого производителя (Models) и общее количество всех товаров по всем этим моделям (Units). В конце группы сортируются по количеству товаров по убыванию.
Используйте предложения HAVING и WHERE в одном запросе (визуальные инструменты базы данных)
В некоторых случаях может потребоваться исключить отдельные строки из групп (с помощью WHERE предложения) перед применением условия к группам в целом (с помощью HAVING предложения).
Предложение HAVING похоже WHERE на предложение, но применяется только к группам в целом (то есть к строкам в результирующем наборе, представляющего группы), в то время WHERE как предложение применяется к отдельным строкам. Запрос может содержать как предложение, WHERE так и HAVING предложение. В этом случае:
- Предложение WHERE применяется сначала к отдельным строкам в таблицах или табличных объектах на панели диаграммы . Группируются только строки, соответствующие условиям в предложении WHERE .
- Затем HAVING предложение применяется к строкам в результирующем наборе. В выходных данных запроса отображаются только группы, соответствующие HAVING условиям. Предложение можно применять HAVING только к столбцам, которые также отображаются в предложении GROUP BY или в агрегатной функции.
Указание предложения WHERE и HAVING для двух присоединенных таблиц
База данных, используемая в этой статье, является базой данных, доступной pubs из Northwind и пабов примеры баз данных для Microsoft SQL Server на GitHub.
Например, соединяются таблицы titles и publishers , чтобы создать запрос, показывающий среднюю цену книги для группы издателей. Требуется средняя цена книги только определенной группы издателей — например, только издателей в штате Калифорния. И даже тогда, вы хотите увидеть среднюю цену только в том случае, если это более $ 10,00.
Вы можете установить первое условие, включив WHERE предложение, которое не карта какие-либо издатели, которые не входят в Калифорнию, прежде чем вычислить средние цены. Для второго условия требуется HAVING предложение, так как условие основано на результатах группировки и суммирования данных. Конечная инструкция SQL может выглядеть следующим образом:
SELECT titles.pub_id, AVG(titles.price) FROM titles INNER JOIN publishers ON titles.pub_id = publishers.pub_id WHERE publishers.state = 'CA' GROUP BY titles.pub_id HAVING AVG(price) > 10;
В visual Database Tools of SQL Server Management Studio можно создавать оба HAVING предложения и WHERE предложения в области условий . По умолчанию при указании условия поиска для столбца условие становится частью HAVING предложения. Однако условие можно изменить, чтобы быть предложением WHERE .
Вы можете создать WHERE предложение и HAVING предложение, включающее один и тот же столбец. Для этого необходимо добавить столбец дважды в область условий , а затем указать один экземпляр в составе HAVING предложения и другой экземпляр в составе WHERE предложения.
Указание условия WHERE в агрегатном запросе
- Укажите группы для запроса. Дополнительные сведения см. в разделе Группирование строк в результатах запроса (визуальные инструменты для баз данных).
- Если он еще не находится в области условий , добавьте столбец, на котором вы хотите создать WHERE условие.
- Очистите столбец Вывод , если столбец данных не является частью предложения GROUP BY или не входит в агрегатную функцию.
- В столбце «Фильтр« укажите WHERE условие. Конструктор запросов и представлений добавляет условие в HAVING предложение инструкции SQL.
Примечание. В качестве примера данной процедуры показан запрос, соединяющий две таблицы titles и publishers .
На этом этапе запроса инструкция SQL содержит HAVING предложение:
SELECT titles.pub_id, AVG(titles.price) FROM titles INNER JOIN publishers ON titles.pub_id = publishers.pub_id GROUP BY titles.pub_id HAVING publishers.state = 'CA'
SELECT titles.pub_id, AVG(titles.price) FROM titles INNER JOIN publishers ON titles.pub_id = publishers.pub_id WHERE publishers.state = 'CA' GROUP BY titles.pub_id;
Связанный контент
- SELECT — НАЛИЧИЕ (Transact-SQL)
- Результаты запросов сортировки и группирования (визуальные инструменты для баз данных)
- Резюмирование результатов запросов (визуальные инструменты для баз данных)
HAVING
После выполнения группировки можно исключать строки из результата выполнения запроса. Для этого в SQL есть предложение HAVING , предназначение которого аналогично предложению WHERE , только работает с группами строк.
Так как HAVING работает с группами строк, то в условиях отсечения используют агрегатные функции вместо значений столбцов (можно использовать выражения из GROUP BY , но проще и эффективней это сделать в WHERE ).
Например найдем категории товаров, в которых только один товар. Все товары:
SELECT category_id, product_id, name FROM product ORDER BY category_id
| category_id | product_id | name |
|---|---|---|
| 3 | 1 | Пылесос S6 |
| 3 | 2 | Холодильник A2 |
| 5 | 12 | Nikon D750 |
| 5 | 11 | Lord Nikon 95 |
| 6 | 5 | Xbox |
| 6 | 3 | Nintendo |
| 6 | 4 | PlayStation |
| 7 | 6 | Наушники S3 |
Посчитаем количество товаров в каждой категории:
SELECT category_id, count(*) FROM product GROUP BY category_id ORDER BY category_id
| category_id | count |
|---|---|
| 3 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 1 |
Оставим категории, в которых только один продукт:
SELECT category_id, count(*) FROM product GROUP BY category_id HAVING count(*) = 1 ORDER BY category_id
| category_id | count |
|---|---|
| 7 | 1 |
Стоит отметить, что использованные в HAVING агрегатные функции нет необходимости использовать в списке выборки. Например, выведем только идентификатор категории товаров:
SELECT category_id FROM product GROUP BY category_id HAVING count(*) = 1 ORDER BY category_id
| category_id |
|---|
| 7 |