← Назад к вопросам

Что такое оконные функции в БД?

1.7 Middle🔥 191 комментариев
#Базы данных и SQL#ООП и паттерны проектирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое оконные функции в SQL

Оконные функции (Window Functions) — это мощный инструмент в SQL, позволяющий выполнять вычисления над набором строк, связанных с текущей строкой, без агрегации всего результата в одну строку. Они работают над "окном" (window) — определенным подмножеством строк относительно текущей записи. Ключевое отличие от обычных агрегатных функций (SUM, AVG) заключается в том, что оконные функции не группируют данные, а сохраняют все исходные строки в результате, добавляя к каждой вычисленное значение.

Основные характеристики оконных функций

  • Сохраняют детализацию строк: Каждая строка исходного запроса остается в выходном результате.
  • Работают над окном: Окно определяется относительно текущей строки с помощью секций (PARTITION BY) и порядка (ORDER BY).
  • Используют специальный синтаксис: Оператор OVER() определяет, как будет построено окно для каждой функции.

Синтаксис и ключевые компоненты

SELECT 
    column1,
    column2,
    WINDOW_FUNCTION(column3) OVER (
        PARTITION BY partition_column
        ORDER BY order_column
        ROWS/RANGE BETWEEN frame_start AND frame_end
    ) AS window_result
FROM table_name;

PARTITION BY — разделяет данные на независимые группы (секции). Функция вычисляется только внутри каждой секции. Если PARTITION BY не указан, окном считается весь набор результатов.

ORDER BY — определяет логический порядок строк внутри каждой секции. Это важно для функций, зависящих от порядка (например, RANK, LEAD).

Фрейм окна (Frame) — точное подмножество строк внутри секции относительно текущей строки. Определяется через ROWS или RANGE.

Типы оконных функций

1. Агрегатные функции как оконные

Те же SUM, AVG, COUNT, MIN, MAX, но применяемые с OVER().

SELECT 
    EmployeeId,
    DepartmentId,
    Salary,
    AVG(Salary) OVER (PARTITION BY DepartmentId) AS AvgDeptSalary,
    SUM(Salary) OVER (PARTITION BY DepartmentId ORDER BY Salary) AS CumulativeSum
FROM Employees;

2. Функции ранжирования

  • ROW_NUMBER() — уникальный последовательный номер строки внутри секции.
  • RANK() — ранжирование с учетом одинаковых значений (возможны "пропуски").
  • DENSE_RANK() — ранжирование без пропусков при одинаковых значениях.
  • NTILE(n) — разделение строк секции на n примерно равных групп.
SELECT 
    ProductName,
    CategoryId,
    Price,
    RANK() OVER (PARTITION BY CategoryId ORDER BY Price DESC) AS PriceRankInCategory
FROM Products;

3. Функции доступа к смежным строкам

  • LAG(column, offset) — значение из предыдущей строки.
  • LEAD(column, offset) — значение из следующей строки.
  • FIRST_VALUE(column) — первое значение в окне.
  • LAST_VALUE(column) — последнее значение в окне (часто требует указания фрейма).
SELECT 
    OrderDate,
    DailyRevenue,
    LAG(DailyRevenue, 1) OVER (ORDER BY OrderDate) AS PrevDayRevenue,
    LEAD(DailyRevenue, 1) OVER (ORDER BY OrderDate) AS NextDayRevenue
FROM DailySales;

4. Функции распределения

  • PERCENT_RANK() — относительный ранг (от 0 до 1).
  • CUME_DIST() — кумулятивное распределение.

Примеры практического применения

Анализ скользящих средних и трендов

SELECT 
    Date,
    Sales,
    AVG(Sales) OVER (
        ORDER BY Date 
        ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING
    ) AS MovingAverage5Days
FROM SalesData;

Вычисление процента от общего в секции

SELECT 
    Department,
    Employee,
    Salary,
    Salary / SUM(Salary) OVER (PARTITION BY Department) * 100 AS SalaryPercentOfDept
FROM Employees;

Поиск разницы с предыдущим значением

SELECT 
    Month,
    Revenue,
    Revenue - LAG(Revenue, 1) OVER (ORDER BY Month) AS MonthlyGrowth
FROM MonthlyReports;

Преимущества использования оконных функций

  • Упрощение сложных запросов: Заменяют множество подзапросов и JOIN-операций.
  • Высокая производительность: Часто оптимизируются лучше, чем коррелирующие подзапросы.
  • Улучшенная читаемость: Логика анализа "в одном месте" — внутри OVER().
  • Расширенный аналитический потенциал: Включение в стандарт SQL (с 2003 года) открыло возможности для сложного анализа без извлечения данных в инструменты BI.

Ограничения и важные замечания

  • Оконные функции нельзя использовать в WHERE, GROUP BY или HAVING — они вычисляются после этих операций. Их можно применять только в SELECT или ORDER BY.
  • Порядок выполнения: Оконные функции вычисляются после агрегаций (GROUP BY) и до окончательного ORDER BY.
  • Фреймы по умолчанию: При наличии ORDER BY и отсутствии явного фрейма используется RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, что может привести к неожиданным результатам.

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