SUM после JOIN врёт: дубли строк
Соединяете заказы с позициями в заказе — обычное дело, обычный JOIN.
SELECT o.id, SUM(o.total) AS выручка
FROM invoices o
JOIN invoice_items i ON i.invoice_id = o.id
GROUP BY o.id;Заказ на сто долларов с пятью позициями внутри вдруг стоит пятьсот. Никто ничего не украл — заказ просто размножился по числу своих же позиций.
«Один заказ, пять строк-детей — и JOIN честно повторил родителя пять раз. Плодятся не деньги. Плодятся строки.»
Поможет ли здесь DISTINCT?
Первый порыв — прилепить DISTINCT сверху. Не поможет: DISTINCT прячет одинаковые строки-результаты, а тут строки-то как раз разные (разные позиции внутри заказа) — маскировка симптома, не лечение причины.
Лечение — свернуть таблицу с детьми до нужной зернистости ДО соединения, а уже потом присоединять к родителю.
WITH позиций_на_заказ AS (
SELECT invoice_id, COUNT(*) AS n
FROM invoice_items GROUP BY invoice_id
)
SELECT o.id, o.total
FROM invoices o
JOIN позиций_на_заказ n ON n.invoice_id = o.id;
-- сумма считается по родителю ДО умножения детьми«Проверка на всякий случай: посчитайте строки до JOIN и после. Стало больше, чем было в исходной таблице, — где-то родитель расплодился.»
Правило: если сумма после соединения выглядит завышенной ровно в несколько раз — считайте, сколько строк-детей приходится на одного родителя. Это и есть множитель, который вас обманул.
Сумма, которая соврала, — не редкость и не экзотика. В архиве есть дело, где она врёт с первой же строки.