Как проверить наличие всех дат для user_id для подсчета новых пользователей по дням
Что проверяют
Умеете ли вы строить непрерывный ряд по дням, а не просто группировать события. День без новых пользователей в GROUP BY просто исчезает, и на графике появляется ложная гладкость. Следом обычно спрашивают, как определить «нового» пользователя и что делать с часовыми поясами.
Как отвечать
Сначала договоритесь об определении: новый пользователь это user_id, у которого первое событие (или регистрация) приходится на этот день. Дальше каркас из трёх шагов:
- первая дата на пользователя:
SELECT user_id, MIN(event_date) AS first_date FROM events GROUP BY user_id. Считать черезCOUNT(DISTINCT user_id)по дням нельзя, так получатся активные, а не новые; - календарь:
generate_series(date '2026-08-01', date '2026-08-31', interval '1 day')::dateв PostgreSQL или готовая таблица-календарь в хранилище. В BigQuery для этого естьGENERATE_DATE_ARRAY, в ClickHouse модификаторWITH FILLуORDER BY; - соединение: календарь слева,
LEFT JOINс первыми датами иCOUNT(f.user_id), который для пустого дня вернёт 0, а не выбросит строку.
Проверка полноты для конкретного user_id: сравните COUNT(DISTINCT event_date) с MAX(event_date) - MIN(event_date) + 1. Если числа не совпали, есть пропуски. Найти сами дыры помогает LAG(event_date) OVER (PARTITION BY user_id ORDER BY event_date): разница больше одного дня означает пропущенный день.
Отдельно проговорите часовой пояс. Если события хранятся в timestamptz, приведите их к поясу отчёта до обрезки до даты, например (created_at AT TIME ZONE 'Europe/Moscow')::date. Иначе пользователь из Владивостока, пришедший в час ночи, попадёт во вчерашний день.
Где спотыкаются
Считают новых через COUNT(DISTINCT user_id) по дням. Получаются активные пользователи, и цифра расходится с продуктовой метрикой в разы.
Строят ряд без календаря. Дни с нулём пропадают, а график в BI-инструменте молча соединяет соседние точки.
Фильтруют период до поиска первой даты. Если в WHERE оставить только август, пользователь, пришедший в июле и вернувшийся в августе, окажется «новым» в августе. Первую дату надо искать по всей истории, а период отрезать уже потом.