🔥 Live Coding: покупка в течение 10 минут после логина
Задача: Есть таблица events:
• user_id • event_time • event_type
Типы событий: • login • purchase
Нужно найти пользователей, у которых покупка произошла в течение 10 минут после логина.
На выходе хотим получить:
• user_id • login_time • purchase_time
Решение:
with logins as ( select user_id, event_time as login_time from events where event_type = 'login' ),
purchases as ( select user_id, event_time as purchase_time from events where event_type = 'purchase' )
select l.user_id, l.login_time, min(p.purchase_time) as purchase_time from logins l inner join purchases p on l.user_id = p.user_id and p.purchase_time >= l.login_time and p.purchase_time <= l.login_time + interval 10 minute group by l.user_id, l.login_time
🧠 Как здесь думаем:
Мы разделяем события на 2 потока: • логины • покупки
Дальше джойним их по user_id.
Но просто соединить по пользователю недостаточно. Нам важно проверить время:
• purchase_time >= login_time • purchase_time <= login_time + interval 10 minute
То есть покупка должна быть: не раньше логина и не позже чем через 10 минут после него ✅
Почему берем min(p.purchase_time)? Потому что после одного логина у пользователя может быть несколько покупок. Обычно в такой задаче нам нужна ближайшая подходящая покупка после логина.
⚠️ Где можно ошибиться:
Не проверить, что покупка идет именно после логина
Если оставить только разницу во времени без условия purchase_time >= login_time, можно случайно захватить покупку, которая была раньше ❌
Получить дубли
После одного логина может быть несколько покупок в окне 10 минут. Если не сделать min() или другой явный выбор, получишь несколько строк на один login.
Перепутать бизнес-смысл
Эта версия запроса отвечает на вопрос: “была ли хотя бы одна покупка в течение 10 минут после логина?”
Если нужно искать строго первую покупку после логина, это уже отдельная логика.
💡 Более аккуратный вариант через оконную функцию:
Если хочется явно взять первую покупку после каждого логина, можно сначала собрать пары, а потом пронумеровать покупки.
with logins as ( select user_id, event_time as login_time from events where event_type = 'login' ),
purchases as ( select user_id, event_time as purchase_time from events where event_type = 'purchase' ),
matched as ( select l.user_id, l.login_time, p.purchase_time, row_number() over ( partition by l.user_id, l.login_time order by p.purchase_time ) as rn from logins l inner join purchases p on l.user_id = p.user_id and p.purchase_time >= l.login_time and p.purchase_time <= l.login_time + interval 10 minute )
select user_id, login_time, purchase_time from matched where rn = 1
🎯 Вывод:
Это типовая задача на поиск последовательности событий во времени.
Главная идея: сначала выделяем нужные типы событий, потом соединяем их по пользователю и времени, а после этого уже выбираем ближайшее подходящее событие.
Такая логика часто встречается в аналитике воронок, продуктовых сценариях и event-based задачах 📊