SELECT user_id, order_id, amount
FROM (
SELECT user_id, order_id, amount,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY amount DESC) AS rn
FROM orders
) t
WHERE rn = 1;
Результат:
user_id | order_id | amount 1 | 105 | 4200 2 | 210 | 3100
WITH ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY email ORDER BY updated_at DESC) AS rn
FROM users
)
SELECT * FROM ranked WHERE rn = 1;
Результат:
email | updated_at a@mail.ru | 2026-03-01 b@mail.ru | 2026-02-14Порешать SQL-задачи в тренажёре →
ROW_NUMBER() — один из самых частых вопросов на собеседовании аналитика. Спрашивают «как достать топ-N по каждой категории» и «как удалить дубли, оставив одну строку». Умей проговорить разницу с RANK/DENSE_RANK и почему фильтр идёт через подзапрос.
ROW_NUMBER даёт уникальные номера (1,2,3,4) даже при равных значениях. RANK при равенстве выдаёт одинаковый ранг и пропускает следующий (1,1,3). DENSE_RANK — одинаковый ранг без пропусков (1,1,2).
Формально да, но порядок номеров станет недетерминированным — движок пронумерует строки как ему удобно. Для воспроизводимого результата ORDER BY внутри OVER практически обязателен.
Нумеруй строки с PARTITION BY по группе и ORDER BY по нужному критерию, затем во внешнем запросе оставь rn <= 3.
Оконные функции · Ранжирование · Дедупликация
RANK · DENSE_RANK · LAG · LEAD · NTILE · SUM OVER
Открыть SQL-тренажёр (565 задач) →