Условие
Таблица uber_transactions(user_id, transaction_date, amount). Для каждого пользователя верните третью по времени транзакцию (если есть). Поля: user_id, transaction_date, amount.
Решение
WITH ranked AS (
SELECT
user_id, transaction_date, amount,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY transaction_date ASC
) AS rn
FROM uber_transactions
)
SELECT user_id, transaction_date, amount
FROM ranked
WHERE rn = 3;Тай-брейк
Если у пользователя две транзакции в один день — порядок недетерминирован. Чтобы стабилизировать — добавить второй ключ:
ORDER BY transaction_date ASC, amount DESCили ORDER BY transaction_id, если он есть.
RANK / DENSE_RANK тут НЕ подходят
RANK = 3 пропустит юзеров, у которых первые две транзакции в один день (получат RANK = 1, 1, 3 — третья будет, но не строго «третья по счёту»). Для «третьей по счёту» — только ROW_NUMBER.
Подводные камни
- Пользователи с < 3 транзакций. Просто не появятся в выходе. Если нужны NULL для них —
LEFT JOINс таблицей пользователей. - Несколько транзакций в один день. ROW_NUMBER даст разный «третий» при каждом запуске, если нет дополнительного ORDER BY.
- Сортировка ASC vs DESC. «Третья» — обычно по времени снизу вверх (1-я, 2-я, 3-я). Не путайте с «третьей с конца».
Эталонный ответ
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY transaction_date) → фильтр = 3. С тай-брейком по второму полю.