CUME DIST: примеры (SQL)

Функция CUME_DIST для анализа распределения данных в SQL
Раздел: Аналитические функции, Оконные
CUME_DIST( OVER [PARTITION BY ] ORDER BY ): float

Функция CUME_DIST в MS SQL Server

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

Функция применяется в запросах с предложением OVER, которое определяет секционирование и порядок сортировки данных. CUME_DIST не принимает явных аргументов, но зависит от порядка, заданного в ORDER BY внутри OVER.

Синтаксис:

CUME_DIST() OVER ( [ partition_by_clause ] order_by_clause )

Возвращаемое значение — число с плавающей точкой в диапазоне от 0 до 1 включительно. Формула расчета для строки R: CUME_DIST = количество строк со значениями ≤ значению R / общее количество строк в секции.

Особенности: результат всегда больше 0 и меньше или равен 1; для одинаковых значений в ORDER BY возвращается одинаковое значение распределения; первое значение в распределении может быть больше 0, если есть несколько строк с минимальным значением.

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

Пример 1: базовое использование для отдела продаж.

SELECT 
    EmployeeID,
    SalesAmount,
    CUME_DIST() OVER (ORDER BY SalesAmount) AS CumeDist
FROM SalesData;
EmployeeID  SalesAmount  CumeDist
----------- ------------ ----------------------
3           100.00       0.25
1           150.00       0.50
4           150.00       0.50
2           300.00       1.00

Пример 2: использование с секционированием (PARTITION BY).

SELECT 
    Department,
    EmployeeID,
    Salary,
    CUME_DIST() OVER (PARTITION BY Department ORDER BY Salary) AS DeptCumeDist
FROM Employees;
Department   EmployeeID  Salary   DeptCumeDist
------------ ----------- -------- ----------------------
IT           5           3000     0.333333333333333
IT           7           4000     0.666666666666667
IT           9           5000     1.000000000000000
Sales        2           2500     0.500000000000000
Sales        4           2500     0.500000000000000
Sales        6           3000     1.000000000000000

Похожие функции в MS SQL

PERCENT_RANK: вычисляет относительный ранг строки в группе. Формула: (RANK - 1) / (общее количество строк - 1). Возвращает значения от 0 до 1, где 0 — первая строка. Отличие от CUME_DIST: PERCENT_RANK показывает позицию относительно других строк, а CUME_DIST — долю строк с меньшими или равными значениями.

NTILE: делит набор строк на указанное количество групп. Помогает в разбиении данных на квантили, но не вычисляет точное распределение.

Предпочтения: CUME_DIST удобна для анализа распределения значений, PERCENT_RANK — для сравнения относительных позиций, NTILE — для создания сегментов (кварталей, децилей).

Типичные ошибки при работе с CUME_DIST

Ошибка 1: пропуск ORDER BY в предложении OVER. Функция требует указания порядка.

-- Неправильно
SELECT CUME_DIST() OVER () FROM SalesData;
-- Правильно
SELECT CUME_DIST() OVER (ORDER BY SalesAmount) FROM SalesData;

Ошибка 2: неправильная интерпретация результатов для одинаковых значений. CUME_DIST для дубликатов возвращает одно значение, что может искажать ожидаемое распределение.

-- Если три строки имеют одинаковое значение, они получат одинаковый CUME_DIST
SELECT Value, CUME_DIST() OVER (ORDER BY Value) FROM TestTable;
Value  CUME_DIST
------ ----------------------
10     1.0  -- все три строки со значением 10 получат 1.0

Ошибка 3: использование NULL-значений. NULL включаются в расчет и считаются наименьшими значениями. Это может привести к неочевидным результатам.

История изменений функции

CUME_DIST была введена в MS SQL Server с версии 2012 вместе с другими оконными функциями. С тех пор существенных изменений в синтаксисе или поведении не было. Основные обновления связаны с оптимизацией производительности в последних версиях SQL Server (2016, 2017, 2019, 2022).

В SQL Server 2012 добавлена возможность использования CUME DIST с секционированием (PARTITION BY). Все последующие версии сохраняют обратную совместимость.

Расширенные примеры применения CUME_DIST

Пример 1: анализ зарплатной вилки в компании.

Пример sql
WITH SalaryAnalysis AS (
    SELECT 
        EmployeeName,
        Salary,
        CUME_DIST() OVER (ORDER BY Salary) * 100 AS SalaryPercentile
    FROM Employees
)
SELECT 
    EmployeeName,
    Salary,
    SalaryPercentile,
    CASE 
        WHEN SalaryPercentile <= 25 THEN 'Нижний квартиль'
        WHEN SalaryPercentile <= 50 THEN 'Средний квартиль'
        WHEN SalaryPercentile <= 75 THEN 'Выше среднего'
        ELSE 'Верхний квартиль'
    END AS SalaryGroup
FROM SalaryAnalysis
ORDER BY SalaryPercentile;

Пример 2: сравнение продаж менеджеров по кварталам.

Пример sql
SELECT 
    ManagerID,
    Quarter,
    Sales,
    CUME_DIST() OVER (PARTITION BY Quarter ORDER BY Sales) AS QuarterCumeDist,
    CUME_DIST() OVER (ORDER BY Sales) AS OverallCumeDist
FROM QuarterlySales
ORDER BY Quarter, Sales;

Пример 3: определение пороговых значений для отсечения.

Пример sql
DECLARE @Threshold DECIMAL(3,2) = 0.9;
WITH RankedProducts AS (
    SELECT 
        ProductID,
        Revenue,
        CUME_DIST() OVER (ORDER BY Revenue) AS RevenueDistribution
    FROM Products
)
SELECT 
    ProductID,
    Revenue,
    RevenueDistribution
FROM RankedProducts
WHERE RevenueDistribution >= @Threshold;
-- Выбирает продукты с доходом выше 90-го процентиля

Пример 4: анализ временных рядов.

Пример sql
SELECT 
    OrderDate,
    DailyRevenue,
    CUME_DIST() OVER (ORDER BY DailyRevenue) AS RevenueCumeDist,
    AVG(DailyRevenue) OVER () AS AvgRevenue
FROM DailyOrders
ORDER BY OrderDate;

Аналоги функции в других СУБД

PostgreSQL и Oracle: поддерживают CUME_DIST с идентичным синтаксисом и поведением.

MySQL: не имеет встроенной CUME_DIST до версии 8.0. В MySQL 8.0 функция доступна с аналогичной MS SQL семантикой.

-- Пример для MySQL 8.0
SELECT 
    name,
    score,
    CUME_DIST() OVER (ORDER BY score) AS cume_dist
FROM students;

SQLite: отсутствует CUME_DIST, но можно эмулировать с помощью подзапросов или агрегатных функций.

Sybase ASE: не поддерживает CUME_DIST, используются пользовательские вычисления.

Общий принцип: в системах без CUME_DIST применяют подзапросы с COUNT и оконными функциями для расчета распределения.

MS SQL CUME_DIST function comments

En
CUME DIST Calculates the cumulative distribution of a value in a group of values