SQL: Вывести третью страницу для каждого пользователя
Условие
У вас есть табличка log, в которой присутствуют колонки user_id, time, page.
Для каждого user_id нужно вывести третью страницу (page) в хронологическом порядке.
Структура таблицы log:
- user_id (integer) - идентификатор пользователя
- time (timestamp) - время посещения
- page (varchar) - название страницы
Ожидаемый результат:
Таблица с колонками user_id и page, где page - это третья посещённая страница данным пользователем.
Источник: реальное собеседование на продуктового аналитика
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Описание подхода
Для решения этой задачи используем оконные функции (window functions) в SQL. Ключевая идея: присвоить каждой странице пользователя номер в хронологическом порядке и отфильтровать только те строки, где номер равен 3.
SQL-запрос
WITH ranked_pages AS (
SELECT
user_id,
page,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY time ASC) as page_number
FROM log
)
SELECT user_id, page
FROM ranked_pages
WHERE page_number = 3
Почему этот подход работает
ROW_NUMBER() — оконная функция, которая нумерует строки в порядке, определённом в ORDER BY:
PARTITION BY user_id— нумерация независима для каждого пользователяORDER BY time ASC— нумерация в хронологическом порядке (от старых событий к новым)WHERE page_number = 3— берём только третьи строки
Альтернативный синтаксис (без CTE)
Если СУБД позволяет использовать WHERE на результаты window-функций:
SELECT user_id, page
FROM (
SELECT
user_id,
page,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY time ASC) as page_number
FROM log
) subquery
WHERE page_number = 3
Важные моменты
- ROW_NUMBER vs RANK: если есть равные timestamps, ROW_NUMBER всё равно присвоит разные номера (по внутреннему порядку), а RANK — одинаковые
- Обработка NULL: если есть пользователи с менее чем 3 страницами, они не появятся в результате (это ожидаемо)
- Производительность: для больших таблиц может потребоваться индекс на (user_id, time)
Пример данных
Дано:
| user_id | time | page |
|---|---|---|
| 1 | 2024-01-01 10:00 | home |
| 1 | 2024-01-01 10:05 | profile |
| 1 | 2024-01-01 10:10 | settings |
| 1 | 2024-01-01 10:15 | logout |
| 2 | 2024-01-01 11:00 | home |
| 2 | 2024-01-01 11:05 | search |
| 2 | 2024-01-01 11:10 | details |
Результат:
| user_id | page |
|---|---|
| 1 | settings |
| 2 | details |
Это стандартная задача на собеседованиях для проверки понимания оконных функций.