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

Синтаксис OVER()

-- window_syntax.sql
aggregate_function() OVER (
    [PARTITION BY column]    -- разбивка на группы
    [ORDER BY column]         -- порядок внутри группы
    [ROWS/RANGE frame]       -- окно строк
)

ROW_NUMBER, RANK, DENSE_RANK

-- ranking.sql
SELECT
    employee_name,
    department,
    salary,
    -- Уникальный номер строки
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num,
    -- Ранг с пропусками при одинаковых значениях
    RANK()       OVER (PARTITION BY department ORDER BY salary DESC) AS rank,
    -- Ранг без пропусков
    DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS d_rank
FROM employees;
SQL аналитические запросы

// Топ-N по группам — классическая задача

Задача: найти 3 самых высокооплачиваемых сотрудника в каждом отделе. Решение: ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) и фильтр WHERE row_num <= 3 в CTE или подзапросе.

LAG и LEAD: доступ к соседним строкам

-- lag_lead.sql
-- Сравнение продаж с предыдущим месяцем
SELECT
    month,
    revenue,
    LAG(revenue, 1) OVER (ORDER BY month) AS prev_month,
    revenue - LAG(revenue, 1) OVER (ORDER BY month) AS change
FROM monthly_sales;

SUM OVER: нарастающий итог

-- running_total.sql
SELECT
    order_date,
    amount,
    SUM(amount) OVER (
        ORDER BY order_date
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS running_total
FROM orders;
SQL оконные функции