Как посчитать Uninstalls в SQL
'electronics' из таблицы products. Какой запрос верный?Содержание:
Зачем считать uninstalls
Удаление приложения — самый честный сигнал «не понравилось». Пользователь может месяцами не открывать приложение, но пока оно висит на телефоне, есть шанс его вернуть пушем или письмом. Удаление обрывает эту связь окончательно: ни пуш прислать, ни ремаркетинг настроить. Поэтому uninstall rate — одна из критических метрик здоровья мобильного продукта.
Особенно важна динамика в первые дни. Если половина установивших удаляет приложение в первую неделю, дело почти всегда в онбординге: человек не дошёл до ценности, запутался или получил не то, что обещала реклама. Разрезы по когортам и по времени до удаления показывают не только «сколько уходит», но и «когда именно» — а это уже подсказка, что чинить.
Формула
Uninstall Rate = uninstalls / installs × 100%Базовый расчёт
Самый простой вариант — помесячно посчитать установки и удаления из таблицы событий и получить долю:
WITH stats AS (
SELECT
DATE_TRUNC('month', event_time) AS month,
COUNT(*) FILTER (WHERE event_type = 'install') AS installs,
COUNT(*) FILTER (WHERE event_type = 'uninstall') AS uninstalls
FROM app_events
WHERE event_time >= '2026-01-01'
GROUP BY 1
)
SELECT
month,
installs,
uninstalls,
uninstalls::NUMERIC * 100 / NULLIF(installs, 0) AS uninstall_rate_pct
FROM stats
ORDER BY month;NULLIF(installs, 0) защищает от деления на ноль, если в каком-то месяце установок не было. Но у такого «наивного» расчёта есть подвох: установки одного месяца могут удаляться в следующем, поэтому доля в лоб занижает реальный отток. Честнее считать по когортам — об этом ниже.
Uninstall rate по когортам
Когортный разрез показывает, когда происходят удаления: группируем пользователей по неделе установки и смотрим, какая доля удалила приложение в течение 7 и 30 дней от своей установки, а не по календарному месяцу.
WITH cohort_installs AS (
SELECT
device_id,
DATE_TRUNC('week', event_time) AS install_week,
event_time AS install_time
FROM app_events
WHERE event_type = 'install'
),
uninstalls AS (
SELECT
device_id,
event_time AS uninstall_time
FROM app_events
WHERE event_type = 'uninstall'
)
SELECT
c.install_week,
COUNT(DISTINCT c.device_id) AS installs,
COUNT(DISTINCT CASE
WHEN u.uninstall_time <= c.install_time + INTERVAL '7 days'
THEN c.device_id
END) AS uninstalled_7d,
COUNT(DISTINCT CASE
WHEN u.uninstall_time <= c.install_time + INTERVAL '30 days'
THEN c.device_id
END) AS uninstalled_30d
FROM cohort_installs c
LEFT JOIN uninstalls u ON u.device_id = c.device_id
GROUP BY c.install_week
ORDER BY c.install_week;Такой расчёт сравнивает каждую когорту с самой собой и убирает искажение из базового варианта: удаление всегда привязано к дате установки конкретного устройства, а не к календарю.
Время до удаления
Ещё полезнее — распределение по времени жизни: через сколько дней после установки люди удаляют приложение. Джойним установку и первое последующее удаление того же устройства и раскладываем разницу по корзинам.
WITH paired AS (
SELECT
i.device_id,
i.event_time AS install_time,
u.event_time AS uninstall_time,
EXTRACT(EPOCH FROM (u.event_time - i.event_time)) / 86400 AS days_to_uninstall
FROM app_events i
JOIN app_events u ON u.device_id = i.device_id
AND u.event_time > i.event_time
AND u.event_type = 'uninstall'
WHERE i.event_type = 'install'
)
SELECT
CASE
WHEN days_to_uninstall <= 1 THEN '< 1 day'
WHEN days_to_uninstall <= 7 THEN '1-7 days'
WHEN days_to_uninstall <= 30 THEN '8-30 days'
WHEN days_to_uninstall <= 90 THEN '31-90 days'
ELSE '90+ days'
END AS bucket,
COUNT(*) AS uninstalls
FROM paired
GROUP BY 1
ORDER BY 1;Форма распределения сразу подсказывает диагноз. Если 60% удалений приходится на первые сутки — почти наверняка сломан онбординг или реклама приводит нецелевую аудиторию. Если пик размазан по 30–90 дням — скорее вопрос удержания и ценности, а не первого впечатления.
Связать метрики удаления с полной картиной удержания и активации помогает практика на реальных задачах — например, в тренажёре на kariernik.ru.
Частые ошибки
Ошибка 1. Трекинг самого события. iOS и Android не сообщают об удалении в реальном времени. Стандартный способ детекта — тихий (silent) пуш: если устройство перестаёт отвечать и токен становится невалидным, приложение считается удалённым. Отсюда следует задержка в несколько дней, и это надо закладывать в отчёты.
Ошибка 2. Переустановка. Пользователь удалил приложение и поставил заново через неделю. Считать это как одну установку или две — вопрос определения, но он должен быть зафиксирован явно, иначе метрики разъедутся между командами.
Ошибка 3. Кросс-девайс. iPhone удалил, iPad оставил. По одному устройству это удаление, но пользователь остался с вами — по человеку это не отток. Если считать по устройствам, а выводы делать про пользователей, получите искажение.
Ошибка 4. Считать краш за удаление. Падение приложения — это не удаление. Это разные события с разными причинами; смешивать их — значит завышать отток и гоняться не за той проблемой.
Ошибка 5. Рассинхрон периодов. Сравнивать установки месяца X с удалениями того же месяца X некорректно: установки месяца X могут удаляться в следующих месяцах. Именно поэтому для честной картины считают по когортам.
Связанные темы
- Как посчитать installs в SQL
- Как посчитать D1/D7/D30 retention в SQL
- Как посчитать churn в SQL
- Как посчитать activation rate в SQL
FAQ
Какой uninstall rate считается нормальным?
Ориентиры для мобильных приложений: к первому дню (D1) удаляют 30–50%, к D7 — 50–70%, к D30 — 70–85%. Мобильный трафик сам по себе даёт высокий отток, поэтому важнее не абсолютное число, а динамика между когортами и сравнение с вашей же историей.
Как вообще обнаружить удаление?
Чаще всего через тихий пуш: сервер шлёт невидимое пользователю уведомление, и если устройство перестаёт подтверждать доставку (токен помечается невалидным), приложение считается удалённым. Именно так работают атрибуционные платформы вроде AppsFlyer и Adjust. Из-за этого детект всегда с задержкой в несколько дней.
Чем удаление отличается от неактивности?
При удалении приложения на устройстве больше нет — вернуть пользователя можно только повторной установкой. Неактивный пользователь приложение сохранил, просто не открывает; его ещё реально реактивировать пушем, письмом или обновлением. Это принципиально разные состояния оттока.
Каковы главные причины удалений?
Обычно это: плохое первое впечатление и сломанный онбординг; чистка памяти на устройстве; переход на приложение-замену; спам пушами. Первая причина — самая управляемая продуктом, поэтому и разрез «время до удаления» так важен.
Есть ли аналог удаления в вебе?
В вебе понятия «удаление» нет — там ближайший аналог это отказ (bounce) и невозврат пользователя. Метрика удаления уникальна для мобильных приложений именно потому, что приложение физически установлено на устройстве.