Как посчитать DAU, WAU, MAU и скользящий MAU на SQL?
- Что такое stickiness DAU/MAU?
DAU — число уникальных пользователей за день: COUNT(DISTINCT user_id) GROUP BY day. MAU календарный — то же по месяцам. Скользящий MAU на каждый день — уникальные за последние 30 дней; его нельзя получить суммой DAU (пользователь посчитается много раз) — нужен join дней с окном событий.
- Stickiness = DAU / MAU — какую долю месяца средний пользователь активен
- COUNT(DISTINCT) по окну в большинстве СУБД не поддерживается — используют самосоединение или приблизительные функции (HyperLogLog)
- Определение «активности» фиксируют заранее
А ещё На больших объёмах — uniq/uniqCombined в ClickHouse, approx_count_distinct
Подробно
Почему нельзя суммировать DAU. Пользователь, заходящий каждый день, войдёт в сумму 30 раз. Уникальные пользователи не аддитивны — это частая ошибка в витринах, где MAU «считают» из DAU.
Производительность. Скользящий подсчёт уникальных — дорогая операция: для каждого дня просматривается окно событий. На больших данных:
- предагрегировать «пользователь — день активности» (одна строка на пару) и считать по ней;
- использовать приблизительные структуры (HyperLogLog), которые объединяются между днями;
- для точного значения — битовые карты пользователей по дням.
Stickiness. DAU/MAU = 0,2 значит, что средний активный за месяц пользователь заходит примерно 6 дней из 30. Для мессенджеров норма выше, для сервисов редких покупок — ниже.
Пример
-- DAU
SELECT event_date, COUNT(DISTINCT user_id) AS dau
FROM events GROUP BY event_date;
-- скользящий MAU (30 дней) на каждую дату
SELECT d.day, COUNT(DISTINCT e.user_id) AS mau_30
FROM generate_series(DATE '2026-09-01', DATE '2026-09-30', INTERVAL '1 day') AS d(day)
JOIN events e
ON e.event_date > d.day - INTERVAL '30 day'
AND e.event_date <= d.day
GROUP BY d.day;Что хотят услышать
- Подсчёт DAU и MAU.
- Почему уникальные неаддитивны.
- Скользящее окно и приблизительные методы.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Скользящий MAU — сумма DAU за последние 30 дней
- ✗DAU — COUNT(*) всех событий за день
- ✓DAU — COUNT(DISTINCT user_id) по дням; MAU нельзя сложить из DAU
- ✗Stickiness = MAU / DAU, чем больше, тем лучше
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.