Раздел 42 · Аналитика данных с нуля

Как решать ad-hoc: уточнить, проверить, посчитать, перепроверить

middle~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Договор с «Монеткой» подписан накануне, и в офисе ещё пахнет тортом. Ночью Бран написал, что выручка после 2.0 падает, и Ким ответил ему за пять минут: «всё из-за релиза». Утром Бран хочет хотя бы одну твёрдую цифру.

Ким не проверял: в его сумме возвраты, эхо вебхуков и покупки тестировщиков, те самые болячки из первого босса. Ещё полгода назад такая цифра ушла бы Брану, и Бран повторил бы её на совете. Лада ставит на доску четыре шага, и сегодня мы пройдём их на вопросе Брана.

За шесть блоков ты научился считать почти всё: выручку, когорты, окна, A/B-тесты. Теперь блок про то, как этим работать. Большая часть задач аналитика это ad-hoc: разовый вопрос, на который ответ нужен сегодня. Разберём, как решать такой вопрос так, чтобы цифра пережила совет директоров.

Врач, а не автомат

Пациент приходит к врачу и говорит: «Болит». Плохой врач сразу выписывает таблетку. Хороший сначала спрашивает: где болит, давно ли, после чего. Потом смотрит анализы. Потом ставит диагноз и проверяет, сходится ли он со всем остальным.

С вопросом заказчика то же самое. «Сколько мы заработали в июне» звучит как одна строка SQL. На деле в этой фразе спрятаны три решения, и каждое меняет ответ. Поэтому ad-hoc решается в четыре шага:

  1. Уточнить вопрос: что считать и за какой период;
  2. Проверить данные: какие болячки сидят в нужных таблицах;
  3. Посчитать;
  4. Перепроверить ответ другим способом, прежде чем отправлять.

Шаг 1. Уточнить вопрос

В «заработали» прячутся три развилки:

  • грязные деньги или чистые: считать ли возвраты, повторные вебхуки и покупки тестировщиков студии;
  • какой июнь: по UTC, как лежит в базе, или по Москве;
  • заработали игроки или студия: магазин приложений забирает свою долю, но этих данных в guild нет.

Хорошее уточнение короткое и предлагает вариант по умолчанию. Не «а что вы имеете в виду?», а «считаю чистые платежи игроков по UTC, без комиссии магазина, ок?». Бран ответил «ок», и у задачи появилось определение. Записывай такие договорённости рядом с цифрой: через месяц кто-нибудь спросит, почему у маркетинга получилось больше.

Определение работает как подпись под цифрой. «70 564 ₽» без подписи можно сравнить с чем угодно и прийти к неверному выводу. «70 564 ₽ чистых платежей по UTC» сравнивают только с такими же числами. Между грязным и чистым июнем разница около 9,4 тысячи рублей: это выручка примерно четырёх обычных июньских дней.

Ещё два вопроса из рабочего чата агентства, на которых потренируемся в квестах:

  • Мира: «Сколько у нас клиентов?» Зарегистрированных, купивших хоть раз или купивших и не отменивших? И считать ли одним клиентом два аккаунта с почтой в разном регистре?
  • Отто: «Сколько заказов опоздало в мае?» Май по какому времени? Отменённые входят? С чем сравнивать время доставки, если оно лежит в UTC, а обещанное время в местном?

Шаг 2. Проверить данные

Прежде чем считать, посмотри на сырые строки за июнь. Хватит одного запроса, который пересчитывает известные болячки в нужном периоде:

SELECT count(*) FILTER (
         WHERE id NOT IN (SELECT min(id) FROM purchases GROUP BY receipt_id)
       ) AS echoes,
       count(*) FILTER (WHERE status = 'refunded') AS refunds,
       count(*) FILTER (
         WHERE player_id IN (SELECT id FROM players WHERE email LIKE '%@studio.dev')
       ) AS testers
FROM purchases
WHERE created_at >= '2026-06-01' AND created_at < '2026-07-01';
 echoes | refunds | testers
--------+---------+---------
      6 |       3 |       9

Каждый FILTER здесь это вопрос «а нет ли тут той болячки?». Если в колонке ноль, болячки в периоде нет, и её фильтр можно не писать. Если не ноль, фильтр нужен, а заодно ясно, сколько он уберёт. В purchases за июнь 149 строк на 79 962 ₽. Среди них:

  • 6 повторов вебхука на 2335 ₽: тот же receipt_id, вторая копия через несколько секунд;
  • 3 возврата на 747 ₽;
  • 9 покупок тестировщиков @studio.dev на 6914 ₽.

Часть строк попадает сразу в две категории, поэтому слагаемые не складываются в разницу один в один. Но порядок ясен: почти 9,4 тысячи рублей из 80 лишние. Все три болячки мы уже встречали в уроке про дубли и пропуски и в боссе «Экономика Пограничья».

урок из курса

Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.