SELECT
user_id,
revenue,
PERCENT_RANK() OVER (ORDER BY revenue) AS pct_rank
FROM users;
Результат:
user_id | revenue | pct_rank --------+---------+--------- 3 | 500 | 0.00 7 | 1200 | 0.50 9 | 4800 | 1.00
SELECT
user_id,
revenue,
PERCENT_RANK() OVER (ORDER BY revenue) AS pct_rank,
CUME_DIST() OVER (ORDER BY revenue) AS cume_dist
FROM users;
Результат:
user_id | revenue | pct_rank | cume_dist --------+---------+----------+---------- 3 | 500 | 0.00 | 0.33 7 | 1200 | 0.50 | 0.67 9 | 4800 | 1.00 | 1.00
SELECT user_id, revenue
FROM (
SELECT
user_id,
revenue,
CUME_DIST() OVER (ORDER BY revenue DESC) AS cd
FROM users
) t
WHERE cd <= 0.10
ORDER BY revenue DESC;
Результат:
user_id | revenue --------+-------- 9 | 4800 15 | 4200Порешать SQL-задачи в тренажёре →
Спрашивают, как выделить топ-10% клиентов по выручке или отнести пользователя к перцентилю. Идут в паре с NTILE (для бакетов) и RANK/DENSE_RANK; важно уметь объяснить разницу с PERCENTILE_CONT.
PERCENT_RANK = (ранг − 1) / (число строк − 1) и для первой строки равна 0. CUME_DIST = доля строк со значением ≤ текущего и всегда больше 0. Первая измеряет положение по рангу, вторая — накопленную долю распределения.
Это обратные операции: PERCENT_RANK по значению даёт его относительный ранг (0..1), а PERCENTILE_CONT по доле (например 0.9) возвращает само значение перцентиля. Первая — оконная функция, вторая — агрегат с WITHIN GROUP.
Отсортируйте по убыванию и возьмите CUME_DIST() OVER (ORDER BY revenue DESC) <= 0.10 в подзапросе. Можно использовать и PERCENT_RANK(), но помните, что у неё пороги немного другие из-за деления на (n − 1).
Оконные функции · Ранжирование
ROW_NUMBER · RANK · DENSE_RANK · LAG · LEAD · NTILE
Открыть SQL-тренажёр (565 задач) →