Слой метрик в SQL: как отделить сырые события от бизнес-показателя
Как построить прозрачный SQL-расчёт через CTE: raw, clean, daily facts и metric layer без копирования формул по дашбордам.
Содержание статьи
Когда формула живёт внутри каждого графика, изменение определения требует ручного обхода всех дашбордов. Спор о цифре превращается в спор о том, какой SQL запускался. Как сделать так, чтобы одна продуктовая метрика не считалась по-разному в пяти отчётах?
Сигнал в данных
Как сделать так, чтобы одна продуктовая метрика не считалась по-разному в пяти отчётах?
Когда формула живёт внутри каждого графика, изменение определения требует ручного обхода всех дашбордов. Спор о цифре превращается в спор о том, какой SQL запускался.
Вместо того чтобы считать DAU в каждом отчёте, создай daily_active_users с одной строкой на дату и сегмент. Дашборд отвечает за фильтр и представление, а не за повторное определение активного действия.
Как устроен расчёт
У каждого слоя свой grain: raw event, clean event, user-day, metric-day. Напиши его рядом с моделью, иначе следующий JOIN легко нарушит расчёт.
Раздели запрос на raw, clean, entity facts и metric output. На каждом шаге добавь контроль строк, уникальных ключей и периода. Название CTE должно говорить о зерне, а не только о технической операции.
Если показатель строится по событиям, отдельно проверь повторную отправку, идентичность пользователя и часовой пояс. Если данные приходят из бизнес-системы, сопоставь техническое поле с тем, как команда реально принимает решение.
вопрос → объект → период → расчёт → проверка → решениеЛюбой пропущенный шаг может изменить смысл итогового числа.
Практический сценарий
Вместо того чтобы считать DAU в каждом отчёте, создай daily_active_users с одной строкой на дату и сегмент. Дашборд отвечает за фильтр и представление, а не за повторное определение активного действия.
Не копируй пример в рабочий отчёт вслепую. Сначала замени названия таблиц и полей, проверь кардинальность связей и запиши, какие строки должны попасть в результат. Хорошая адаптация сохраняет логику, но делает допущения видимыми.
| Слой | Зерно | Проверка |
|---|---|---|
| raw | одно входное событие | доставка и ключ |
| clean | одно валидное событие | NULL и дубли |
| facts | user × day | уникальность |
| metric | day × segment | сверка с baseline |
WITH clean_events AS (\n SELECT DISTINCT user_id, event_at::date AS event_date\n FROM raw_events\n WHERE event_name = 'core_action' AND user_id IS NOT NULL\n), daily_users AS (\n SELECT event_date, user_id FROM clean_events GROUP BY event_date, user_id\n)\nSELECT event_date, COUNT(*) AS active_users\nFROM daily_users\nGROUP BY event_date\nORDER BY event_date;Контрольные случаи
Слой превращается в формальность, если он скрывает timezone, исключения и незрелые даты. Также опасно делать слишком широкий «универсальный» CTE, который невозможно проверить.
Отдельно протестируй пустой результат, NULL, дубль, граничную дату и объект без связанной записи. Эти случаи не являются редкими исключениями: именно они чаще всего превращают рабочий показатель в красивую, но неверную цифру.
- Не смешивай зрелые и незрелые периоды без отдельной подписи.
- Не заменяй проверку качества тем, что запрос просто выполнился.
- Не делай причинный вывод из одного разреза.
Чтение визуализации
График здесь нужен не для украшения статьи. Он помогает увидеть форму сигнала: тренд, разрыв между сегментами, хвост распределения или этап, на котором теряется объект. Сначала прочитай оси и единицы, затем сравни с таблицей и только после этого формулируй вывод.
На визуализации «Путь от события к метрике» сравнивай не только максимальное значение. Проверь, одинаковы ли базы, не скрыта ли неполная дата и не меняется ли знаменатель от категории к категории.
Условный пример: каждый слой уменьшает технический шум и фиксирует новое зерно.
Небольшое упражнение
Возьми одну метрику из существующего отчёта и вынеси её в четыре слоя. На каждом шаге зафиксируй ожидаемое число строк и два контрольных значения.
После упражнения напиши вывод в двух версиях. Первая — техническая: какие строки и условия дали результат. Вторая — для команды: что изменилось, насколько это надёжно и какое действие стоит проверить. Если эти версии противоречат друг другу, вернись к определению показателя.
- Собери контрольный пример из пяти-десяти строк.
- Сверь итог с независимым способом расчёта.
- Проверь хотя бы один крайний случай.
- Зафиксируй дату, версию схемы и ограничение.
Что передать команде
Чем больше потребителей у метрики, тем важнее общий слой. Для разовой разведки достаточно локального запроса, но результат нельзя выдавать за официальный показатель без владельца.
Сильный аналитический материал не обещает абсолютной уверенности. Он показывает, как получить число, где оно может ошибиться и какое решение можно принять уже сейчас. Такой формат хорошо переносится в дашборд, SQL-тренажёр, собеседование и рабочее обсуждение с командой.
Материалы по теме
EXPLAIN в PostgreSQL для аналитика: как найти медленный запрос
Понятный гайд по EXPLAIN и EXPLAIN ANALYZE: scan, join, sort, rows estimate и безопасный разбор производительности SQL.

Подзапросы в SQL: когда нужен вложенный SELECT, CTE или JOIN
Как выбрать между подзапросом, CTE и JOIN: где меняется зерно данных, почему скалярный подзапрос дорого стоит и как разложить длинный запрос на проверяемые слои.
Собеседование BI-аналитика: дашборды, Excel, SQL и бизнес-кейсы
Практический гайд по собеседованию BI-аналитика: как проектировать дашборд, выбирать KPI, проверять данные, отвечать про Excel и защищать вывод перед бизнесом.