← Назад к вопросам

SQL: Вывести третью страницу для каждого пользователя

2.0 Middle🔥 201 комментариев
#SQL и базы данных

Условие

У вас есть табличка log, в которой присутствуют колонки user_id, time, page.

Для каждого user_id нужно вывести третью страницу (page) в хронологическом порядке.

Структура таблицы log:

  • user_id (integer) - идентификатор пользователя
  • time (timestamp) - время посещения
  • page (varchar) - название страницы

Ожидаемый результат:

Таблица с колонками user_id и page, где page - это третья посещённая страница данным пользователем.

Источник: реальное собеседование на продуктового аналитика

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

Описание подхода

Для решения этой задачи используем оконные функции (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_idtimepage
12024-01-01 10:00home
12024-01-01 10:05profile
12024-01-01 10:10settings
12024-01-01 10:15logout
22024-01-01 11:00home
22024-01-01 11:05search
22024-01-01 11:10details

Результат:

user_idpage
1settings
2details

Это стандартная задача на собеседованиях для проверки понимания оконных функций.

SQL: Вывести третью страницу для каждого пользователя | PrepBro