FirebirdSQL logo

Агрегатные функции выполняют вычисление на наборе значений и возвращают одиночное значение.Агрегатные функции, за исключением COUNT, не учитывают значения NULL.Агрегатные функции часто используются совместно с предложением GROUP BY.

Агрегатные функции могут быть использованы в качестве выражений только в следующих случаях:

  • Список выбора инструкции SELECT (вложенный или внешний запрос);

  • Предложение HAVING.

Синтаксис агрегатных функций
<aggregate_function> ::=
  aggragate_function ([ALL | DISTINCT] <expr>)
  [FILTER (WHERE <condition>)]

Агрегатные функции также могут использоваться как оконные с предложением OVER ().Подробнее смотри в Оконные (Аналитические) функции.

Предложение FILTER

Предложение FILTER расширяет агрегатные функции дополнительным предложением WHERE.Если используется предложение FILTER, то результат агрегата строится только из строк, которые также удовлетворяют условию в дополнительном предложении WHERE.

Как правило, предложение фильтра может быть реализовано с использованием выражения CASE внутри агрегатной функции: условие фильтра должно быть помещено в предложение WHEN, значение, которое должно быть агрегировано в предложение THEN.Поскольку агрегатные функции обычно пропускают значения NULL, неявное предложение ELSE NULL достаточно, чтобы игнорировать не подходящие под условия фильтрации строки.Следующие два выражения эквивалентны:

SUM(<expression>) FILTER(WHERE <condition>)

и

SUM(CASE WHEN <condition> THEN <expression> END)

Для COUNT(*) этот пример выглядит иначе, потому что выражение “*” не может быть использовано в предложении THEN.Вместо этого обычно используется любое константное значение не равное NULL.

COUNT(*) FILTER(WHERE <condition>)

и

SUM(CASE WHEN <condition> THEN 1 END)
Примеры FILTER
Example 1. Использование предложения FILTER
SELECT
  invoice_year,
  SUM(revenue) FILTER (WHERE invoice_month = 1) AS jan_revenue,
  SUM(revenue) FILTER (WHERE invoice_month= 2) AS feb_revenue,
  ...
  SUM(revenue) FILTER (WHERE invoice_month = 12) AS dec_revenue
FROM (
  SELECT
    EXTRACT(YEAR FROM invoices.invoice_date) AS invoice_year,
    EXTRACT(MONTH FROM invoices.invoice_date) AS invoice_month,
    invoices.revenue AS revenue
  FROM invoices
)
GROUP BY invoice_year