Агрегатные функции
Обзор
Агрегатные функции вычисляют результат по набору входных значений. Например, можно вычислить количество, сумму, среднее, максимальное и минимальное значение по набору строк.
Пример:
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
.