Выручка на дашборде выше бухгалтерской в несколько раз
Дашборд по каналам собирается запросом:
SELECT u.channel,
COUNT(DISTINCT u.user_id) AS users,
SUM(o.amount) AS revenue
FROM users u
JOIN orders o ON o.user_id = u.user_id
JOIN app_events e ON e.user_id = u.user_id
GROUP BY u.channel;
Число пользователей выглядит правдоподобно, а выручка в несколько раз выше, чем в биллинге. Что происходит и как чинить?
- Нужно написать SUM(DISTINCT o.amount): без DISTINCT суммирование учитывает повторяющиеся значения многократно, а с ним каждая сумма заказа попадёт в итог ровно один раз, и выручка сойдётся с биллингом без изменения структуры запроса
- Причина в JOIN вместо LEFT JOIN: часть заказов теряется при соединении, а оставшиеся получают завышенный вес в сумме
- Не хватает o.order_id в GROUP BY: после его добавления дубли исчезнут, а разрез по каналам сохранится
- Соединение с событиями размножает строки заказов: сумма каждого заказа попадает в SUM столько раз, сколько у пользователя событий. Агрегаты разной гранулярности надо считать отдельными подзапросами и соединять уже готовые агрегаты по user_id или channel
