Как посчитать MAU в SQL

Закрепи формулу MAU в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать MAU в Telegram

Зачем MAU

«Сколько у нас активных пользователей за месяц?» — самый частый вопрос менеджмента. Цифра звучит просто, но: считать calendar month (1-30 апреля) или rolling 30 дней? Включать ли регистрации, не закончившие onboarding? Что считать «active»?

MAU — фундаментальная метрика для большинства продуктов. В статье — SQL и нюансы.

Что такое MAU

MAU (Monthly Active Users) — уникальные пользователи, совершившие минимум одно действие за период в месяц.

MAU = COUNT(DISTINCT user_id) where date ∈ месяц

Что считать «active» — определяется командой: открыл приложение, или совершил key event (например, отправил сообщение, оформил заказ).

Базовый расчёт

Данные: events(user_id, event_date, event_type).

SELECT
    DATE_TRUNC('month', event_date) AS month,
    COUNT(DISTINCT user_id) AS mau
FROM events
WHERE event_date >= '2026-01-01'
  AND event_date <  '2026-05-01'
GROUP BY 1
ORDER BY 1;

Важно: DATE_TRUNC('month', ...) группирует по календарному месяцу. Если месяц неполный — MAU занижен.

Calendar MAU vs Rolling 30-day

Calendar MAU

Активные за календарный месяц (1-30/31 числа). Простой и понятный.

Rolling 30-day MAU

Активные за последние 30 дней (катящееся окно). Не зависит от границ месяца, гладкая кривая.

WITH dates AS (
    SELECT generate_series('2026-04-01'::DATE, '2026-04-30'::DATE, INTERVAL '1 day')::DATE AS day
)
SELECT
    d.day,
    COUNT(DISTINCT e.user_id) AS rolling_mau
FROM dates d
JOIN events e
  ON e.event_date > d.day - INTERVAL '30 days'
 AND e.event_date <= d.day
GROUP BY d.day
ORDER BY d.day;

Rolling MAU не имеет «провалов» на стыке месяцев и лучше для долгосрочных трендов.

Закрепи формулу MAU в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать MAU в Telegram

MAU по сегментам

SELECT
    DATE_TRUNC('month', e.event_date) AS month,
    u.acquisition_channel,
    COUNT(DISTINCT e.user_id) AS mau
FROM events e
JOIN users u ON u.user_id = e.user_id
WHERE e.event_date >= '2026-01-01'
GROUP BY 1, 2
ORDER BY 1, mau DESC;

Или по типу события:

SELECT
    DATE_TRUNC('month', event_date) AS month,
    COUNT(DISTINCT user_id) AS open_app_mau,
    COUNT(DISTINCT CASE WHEN event_type = 'purchase' THEN user_id END) AS purchase_mau
FROM events
WHERE event_date >= '2026-01-01'
GROUP BY 1;

«Качественный MAU» (с key event) обычно меньше total MAU.

Частые ошибки

Ошибка 1. Считать неполный месяц. 13 мая 2026 — MAU за май неполный. Используйте month-to-date.

Ошибка 2. Дубли user_id. Если в events user_id записан с пробелами / разными регистрами — DISTINCT не сработает. Нормализуйте.

Ошибка 3. Включать ботов. Без фильтра is_bot = false MAU завышен. В мобайле особенно (тестовые установки, эмуляторы).

Ошибка 4. Timezone. DATE_TRUNC в UTC даёт MAU «по UTC». Для МСК-продукта приведите к нужной зоне: event_date AT TIME ZONE 'Europe/Moscow'.

Ошибка 5. Confusion с unique users за period. «Unique users за квартал» ≠ MAU × 3. Юзер мог быть активен 1 раз во всём квартале — считается 1 раз в total quarterly, но входил бы в MAU каждого месяца, если был активен в каждый.

Ошибка 6. Calendar vs rolling. Сравнение «MAU апреля calendar» с «MAU last 30d rolling» — некорректно. Зафиксируйте определение.

Связанные темы

FAQ

MAU или DAU?

DAU — для высокочастотных (соцсети, мессенджеры). MAU — для среднечастотных (e-com, банк, СМИ). Большинство продуктов считают обе.

Calendar или rolling?

Calendar — для отчётности по периодам. Rolling — для трендов. В дашборды обычно ставят обе.

Что значит «active»?

Договоритесь в команде. Чаще всего «открыл приложение/сайт». Но «качественный MAU» считают по key event.

Размер MAU vs market?

Total addressable market (TAM) → serviceable addressable market (SAM) → MAU. Доля MAU/SAM показывает penetration.

MAU упал — что делать?

Декомпозиция: 1) acquisition (новые юзеры падают?), 2) retention (старые отваливаются?), 3) engagement (тот же юзер реже заходит?). Каждое — отдельный fix.