Договор с «Монеткой» подписан накануне, и в офисе ещё пахнет тортом. Ночью Бран написал, что выручка после 2.0 падает, и Ким ответил ему за пять минут: «всё из-за релиза». Утром Бран хочет хотя бы одну твёрдую цифру.
Ким не проверял: в его сумме возвраты, эхо вебхуков и покупки тестировщиков, те самые болячки из первого босса. Ещё полгода назад такая цифра ушла бы Брану, и Бран повторил бы её на совете. Лада ставит на доску четыре шага, и сегодня мы пройдём их на вопросе Брана.
За шесть блоков ты научился считать почти всё: выручку, когорты, окна, A/B-тесты. Теперь блок про то, как этим работать. Большая часть задач аналитика это ad-hoc: разовый вопрос, на который ответ нужен сегодня. Разберём, как решать такой вопрос так, чтобы цифра пережила совет директоров.
Врач, а не автомат
Пациент приходит к врачу и говорит: «Болит». Плохой врач сразу выписывает таблетку. Хороший сначала спрашивает: где болит, давно ли, после чего. Потом смотрит анализы. Потом ставит диагноз и проверяет, сходится ли он со всем остальным.
С вопросом заказчика то же самое. «Сколько мы заработали в июне» звучит как одна строка SQL. На деле в этой фразе спрятаны три решения, и каждое меняет ответ. Поэтому ad-hoc решается в четыре шага:
- Уточнить вопрос: что считать и за какой период;
- Проверить данные: какие болячки сидят в нужных таблицах;
- Посчитать;
- Перепроверить ответ другим способом, прежде чем отправлять.
Шаг 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 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.