Короткий ответ
AVG(amount) игнорирует строки с NULL и делит сумму только на количество заказов с заполненной суммой, поэтому при наличии «битых» заказов с NULL вместо суммы средний чек окажется завышен или занижен по сравнению с ожиданием «сумма всех заказов / общее число заказов».
Как это работает подробнее
Как это работает: агрегатные функции в SQL по умолчанию пропускают NULL-значения при вычислении; то есть AVG фактически считает SUM(ненулевых значений) / COUNT(ненулевых значений), а не делит на общее количество строк в группе (COUNT(*)).
Пример кода
PostgreSQL: среднее и NULL
SELECT
COUNT(*) AS total_orders,
COUNT(amount) AS orders_with_amount,
AVG(amount) AS avg_known_amount,
SUM(amount) / NULLIF(COUNT(*), 0) AS avg_per_order
FROM orders;Что использовать на практике
- На практике: перед доверием к
AVGважно явно проверить, сколько строк имеютNULLв этом поле (COUNT(*) - COUNT(amount)), и понять причину — технический сбой интеграции, легитимный «пустой» заказ (например, отменённый до оплаты) или что-то ещё. ЕслиNULLна самом деле должен означать 0, нужно явно привести это черезCOALESCE(amount, 0)до агрегации, а не полагаться на поведениеAVGпо умолчанию. - Проверка: Если
total_orders = 1000,orders_with_amount = 900, две версии среднего будут отличаться. Проверка: расследовать 100 заказов сNULLчерез выборкуSELECT * FROM orders WHERE amount IS NULL LIMIT 20и понять их природу.
Подводные камни
- Частые ошибки: интерпретируют высокий
AVG(amount)как рост среднего чека, когда на самом деле просто увеличилась доля заказов сNULL(например, из-за сбоя одного из источников данных), которыеAVGпросто не учитывает, искажая знаменатель.