Можно ли использовать CTE с INTERVAL для выделения визитов за следующие 7 дней?
Что проверяют
Понимаете ли вы, что CTE это просто именованный подзапрос, а вся сложность вопроса в работе с датами. Следом обычно уточняют, входит ли сегодняшний день и как посчитать визиты за семь дней после первого захода пользователя.
Как отвечать
Да, можно. CTE сама ничего не фильтрует, условие по интервалу пишется в WHERE внутри неё или снаружи. Сначала уточните постановку: семь дней от сегодня или от события пользователя. Первый вариант в PostgreSQL:
WITH upcoming AS (SELECT * FROM visits WHERE visit_at >= current_date AND visit_at < current_date + INTERVAL '7 days') SELECT ... FROM upcoming
Ключевые детали:
- полуоткрытый интервал:
>=для начала и<для конца.BETWEENвключает обе границы: по колонкеdateусловиеBETWEEN current_date AND current_date + 7захватит восемь календарных дней, а поtimestampпоследний день попадёт в выборку одной точкой, полуночью; - диалект: в PostgreSQL
INTERVAL '7 days'илиcurrent_date + 7для типаdate, в MySQLCURDATE() + INTERVAL 7 DAY, в ClickHousetoday() + INTERVAL 7 DAY, в SQL ServerINTERVALнет, тамDATEADD(day, 7, CAST(GETDATE() AS date)); - часовой пояс:
current_dateсчитается по поясу сессии. Если визиты лежат вtimestamptz, а отчёт нужен по Москве, пояс задают явно; - индекс: условие на голую колонку использует индекс, а
visit_at::date BETWEEN ...обычный индекс поvisit_atуже не задействует.
Для варианта «семь дней после первого визита» первая CTE находит MIN(visit_at) по каждому пользователю, а основной запрос джойнит визиты с условием v.visit_at >= f.first_at AND v.visit_at < f.first_at + INTERVAL '7 days'. Это типичная заготовка для расчёта удержания.
Где спотыкаются
Пишут BETWEEN и не замечают лишний или потерянный день на границе. Результат при этом зависит от типа колонки, а полуоткрытый интервал ведёт себя одинаково.
Думают, что CTE ускоряет запрос или кеширует результат. В PostgreSQL с 12-й версии CTE, на которую ссылаются один раз, встраивается в основной запрос, а раньше служила барьером для оптимизатора.
Не уточняют, от какой точки считать семь дней, и решают не ту задачу.