Агрегатные функции
Обзор
Агрегатные функции вычисляют результат по набору входных значений. Например, можно вычислить количество, сумму, среднее, максимальное и минимальное значение по набору строк.
Пример:
SELECT MIN(public_year) FROM book;
Результат:
min ------ 1869
Чтобы использовать агрегатную функцию в выражении WHERE, используйте подзапрос. Следующий пример возвращает название самой старой книги:
SELECT title FROM book WHERE public_year = (SELECT min(public_year) FROM book);
Результат:
title --------------- War and Peace
Также можно комбинировать агрегатные функции с GROUP BY.
Например, получим самую старую книгу каждого жанра:
SELECT genre, min(public_year) public_year FROM book GROUP BY genre;
Результат:
genre | public_year -----------------+------------- science fiction | 1895 fantasy | 1937 novel | 1869
Чтобы фильтровать полученные значения, используйте HAVING:
SELECT genre, min(public_year) public_year
FROM book GROUP BY genre HAVING min(public_year) < 1900;
Результат:
genre | min -----------------+------ science fiction | 1895 novel | 1869
|
ПРИМЕЧАНИЕ
Существует фундаментальное различие между выражениями WHERE и HAVING. WHERE выбирает входные строки перед группировкой и вычислением агрегатных функций. WHERE определяет, какие строки включаются в агрегатные вычисления. HAVING выбирает строки после группировки и расчета агрегатных функций. WHERE не может содержать агрегатные функции, а HAVING всегда их содержит.
Если вам нужно использовать дополнительные условия, добавьте их в WHERE, а не HAVING. Этот подход позволяет избежать агрегатных вычислений для строк, которые не соответствуют дополнительным условиям.
|
Полный список предопределенных агрегатных функций можно найти по ссылке: Aggregate functions.
Синтаксис агрегатных выражений
Агрегатное выражение может записываться одним из следующих способов:
-
Первая форма агрегатного выражения вызывает агрегатную функцию один раз для каждой входящей строки в соответствии с указанным выражением:
<название_агрегатной_функции> (<выражение> [ , ... ] [<order_by_выражение> ]) [FILTER (WHERE <значение_filter>)]Где:
-
<название_агрегатной_функции>— название агрегатной функции; -
<выражение>— выражение значения, которое не содержит какого-либо агрегатного выражения или вызова оконной функции; -
<order_by>— необязательный параметр, который указывает порядок сортировки; -
<значение_filter>— необязательный параметр, содержащий условие фильтра.Пример:
SELECT MIN(public_year) FROM book;
-
-
Вторая форма агрегатного выражения содержит модификатор
ALL. ПосколькуALLявляется модификатором по умолчанию, вторая форма эквивалентна первой.<название_агрегатной_функции> (ALL <выражение> [ , ... ] [<order_by_выражение>]) [FILTER (WHERE <значение_filter>)] -
Третья форма вызывает агрегатную функцию один раз для каждого уникального значения выражения или набора уникальных значений для нескольких выражений.
<название_агрегатной_функции> (DISTINCT <выражение> [ , ... ] [<order_by_выражение>]) [FILTER (WHERE <значение_filter>)]Следующее выражение возвращает количество уникальных названий книг из таблицы с заказами:
SELECT COUNT (DISTINCT(book_title)) FROM orders; -
Четвертая форма вызывает агрегатную функцию один раз для каждой строки. Поскольку выражение, задающее входящие значения, отсутствует, эта форма применима только к функции
COUNT(*).<название_агрегатной_функции> ( * ) [FILTER (WHERE <значение_filter>)] -
Пятая форма используется с агрегатными функциями, выполняемыми над упорядоченным набором значений (например,
array_agg,string_agg,rankиpercentile). Результат выполнения этих функций зависит от порядка входных строк. Для этих функций параметрorder_byявляется обязательным.<название_агрегатной_функции> ([<выражение> [ , ... ] ]) WITHIN GROUP(<order_by_выражение>) [FILTER (WHERE <значение_filter>)]Выражение
order_byимеет тот же синтаксис, что иORDER BY, используемый на уровне запроса, но не может содержать номера и имена выходных столбцов.Пример:
SELECT array_agg(field1 ORDER BY field2 DESC) FROM table1;Если вы вызываете агрегатную функцию с несколькими аргументами,
ORDER BYдолжен быть помещен после всех аргументов:SELECT string_agg(field1, ',' ORDER BY field1) FROM table1;Если
DISTINCTуказан в дополнение кORDER BY, выражениеORDER BYдолжно соответствовать аргументам агрегатной функции. Сортировка по значениям, не включенным в списокDISTINCT, невозможна.Для агрегатной функции с упорядоченным набором входных значений, вы можете поместить выражение
order_byвнутрь выраженияWITHIN GROUP(…). В этом случае выражения вorder_byвычисляются один раз для каждой входящей строки как обычные агрегатные аргументы, сортируются в соответствии с требованиямиorder_byи передаются агрегатной функции в качестве входных аргументов. Еслиorder_byне находится вWITHIN GROUP, оно не рассматривается как аргумент агрегатной функции. Выражения аргументов, предшествующиеWITHIN GROUP, если таковые имеются, называются прямыми аргументами, чтобы отличить их от агрегированных аргументов, перечисленных в выраженииorder_by. Прямые аргументы обрабатываются один раз за вызов агрегатной функции. Они могут содержать переменные, только если эти переменные сгруппированы поGROUP BY. Прямые аргументы обычно используются для единственного значения на расчет агрегации (например, доли процентилей). Если список прямых аргументов пуст, напишите().Пример:
SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY income) FROM households;
Для всех типов агрегатных выражений, перечисленных выше, значение_filter является необязательным параметром. Если указан FILTER, в агрегатную функцию передаются только те входящие строки, для которых значение_filter вычисляется как true.
Например, имеется следующая таблица:
id | book_title | public_year ----+-------------------------------------+------------- 1 | Mrs. Dalloway | 1925 2 | To the Lighthouse | 1927 3 | To Kill a Mockingbird | 1960 4 | The Great Gatsby | 1925 5 | The Lord of the Rings | 1955 8 | War and Peace | 1869 7 | The Hobbit, or There and Back Again | 1937 9 | Hyperion | 1989 10 | The Time Machine | 1895 6 | 1984 | 1949
Выполним запрос с вызовом агрегатной функции COUNT(*) и заданным фильтром:
SELECT
COUNT(*) AS unfiltered,
COUNT(*) FILTER (WHERE public_year < 1900) AS filtered
FROM book;
Результат:
unfiltered | filtered
------------+----------
10 | 2
Большинство агрегатных функций игнорируют входящее значение NULL, а строки, в которых одно или несколько значений содержат NULL, отбрасываются. Это верно для всех предопределенных агрегатных функций, если не указано иное. Например, COUNT(*) возвращает общее количество входных строк, COUNT(field1) возвращает количество входных строк, где field1 не равно нулю, а COUNT(DISTINCT field1) возвращает количество уникальных строк с ненулевыми значениями field1.