Перейти к основному содержимому

3.07. Функции

Разработчику Аналитику Тестировщику
Архитектору Инженеру

Агрегатные функции SQL

В SQL есть множество видов функций - агрегатные, оконные, текстовые функции, числовые функции, функции даты и времени, функции преобразования типов данных, системные функции.

Агрегатные функции – это специальные функции в SQL, которые выполняют вычисления над группой значений, и возвращают одно (итоговое) значение. Они используются для анализа данных: подсчёт, суммирование, усреднение, нахождение максимума/минимума среди набора и другое.

Обычно агрегатные функции применяются так:

  • вместе с SELECT;
  • с GROUP BY для группировки результатов;
  • игнорируют значения NULL, если специально не указано иное.

Основные агрегатные функции:

ФункцияНазначениеПример
COUNT()Считает количество записейSELECT COUNT(*) FROM Users;
SUM()Суммирует значения столбцаSELECT SUM(Price) FROM Orders;
AVG()Вычисляет среднее значениеSELECT AVG(Age) FROM Users;
MIN()Находит минимальное значениеSELECT MIN(Price) FROM Products;
MAX()Находит максимальное значениеSELECT MAX(Age) FROM Users;

Примеры использования:

  1. Подсчёт всех пользователей:
SELECT COUNT(*) AS TotalUsers FROM Users;

COUNT, наверное, сама часто используемая функция из агрегатных. Часто нужно посчитать, сколько в таблице записей, особенно если нужно добавить фильтрацию, к примеру, сколько у нас есть несовершеннолетних пользователей.

  1. Средний возраст пользователей:
SELECT AVG(Age) AS AvgAge FROM Users;
  1. Общая сумма продаж:
SELECT SUM(Amount) AS TotalSales FROM Orders;
  1. Минимальная и максимальная зарплата:
SELECT MIN(Salary), MAX(Salary) FROM Employees;
  1. Использование с GROUP BY – количество вопросов по категориям:
SELECT CategoryId, COUNT(*) AS QuestionCount
FROM Questions
GROUP BY CategoryId;

Важно:

  • COUNT(*) считает все строки;
  • COUNT(column) считает только непустые (NOT NULL) значения в указанном столбце;
  • Агрегатные функции обычно нельзя использовать напрямую в WHERE, но можно в HAVING (при использовании GROUP BY). Агрегатные функции работают после фильтрации строк, поэтому для них нужно HAVING.
  • В запросах с GROUP BY в SELECT должны быть либо агрегатные функции, либо поля из GROUP BY - если в SELECT есть агрегатная функция, все неагрегированные столбцы должны быть в GROUP BY.

Оконные функции

Оконные функции – мощный инструмент, который позволяет выполнять сложный анализ данных без сложных подзапросов или группировок, сохраняя при этом все исходные строки.

Оконная функция – функция, которая вычисляет значения по группе строк, относящихся к текущей строке, не сводя всё к одной строке (как делает GROUP BY), а сохраняя контекст всех строк.

Хорошая шпаргалка по оконным функциям есть здесь:

https://learnsql.com/blog/sql-window-functions-cheat-sheet/

Допустим, у нас есть таблица Sales:

SaleIDProductAmount
1Apple100
2Banana50
3Apple80
4Banana70

Для каждой продажи мы хотим показать её сумму и общую сумму по продукту. Без оконных функций нам придётся делать JOIN между исходной таблицей и результатом агрегации – громоздко. С оконной функцией:

SELECT 
Product,
Amount,
SUM(Amount) OVER (PARTITION BY Product) AS TotalPerProduct
FROM Sales;

Результат:

ProductAmountTotalPerProduct
Apple100180
Banana50120
Apple80180
Banana70120

Все строки на месте, но каждая содержит агрегированное значение по своей группе.

Синтаксис:

function_name(...) OVER (
[PARTITION BY ...]
[ORDER BY ...]
[frame_clause]
)
  • function_name(...) – агрегатная или специальная оконная функция (SUM, ROW_NUMBER, RANK).
  • OVER (...) – указывает, что это оконная функция.
  • PARTITION BY ... – аналог GROUP BY, но не сворачивает данные. Разбивает данные на группы (партиции), но не объединяет строки в одну, все исходные строки остаются на месте, а внутри каждой партиции работает сама функция:
SUM(Amount) OVER (PARTITION BY Product)

ORDER BY ... – определяет порядок строк внутри окна, нужен для расчёта накопленных итогов, присвоения рангов, работы с фреймами:

AVG(Amount) OVER (PARTITION BY Product ORDER BY SaleDate)

frame_clause – определяет, какие строки включаются в окно. Необязательный. Частые варианты - ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW (от начала до текущей строки), ROWS BETWEEN 2 PRECEDING AND CURRENT ROW (три последние строчки), RANGE (диапазон значений):

SUM(Amount) OVER (
PARTITION BY Product
ORDER BY SaleDate
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS RunningTotal

Прочие функции

Функции ранжирования возвращают позицию/ранг внутри окна:

  1. ROW_NUMBER() нумерует строки в порядке сортировки:
ROW_NUMBER() OVER (ORDER BY Salary DESC)
  1. RANK() назначает ранг, пропуская следующие числа при совпадении:
RANK() OVER (PARTITION BY Department ORDER BY Salary DESC)
  1. DENSE_RANK() аналогичен RANK, но без пропусков.
  2. NTILE(n) – делит набор на n равных частей:
NTILE(4) OVER (ORDER BY Score DESC)

Функции смещения позволяют обращаться к соседним строкам:

  1. LAG(column, offset, default_value) возвращает значение из предыдущей строки:
LAG(Salary, 1, 0) OVER (ORDER BY Date)
  1. LEAD(column, offset, default_value) возвращает значение из следующей строки:
LEAD(Score) OVER (PARTITION BY StudentId ORDER BY ExamDate)