1. Know the grain before you join
Always identify what one row represents in your base table before adding joins or aggregates. A row in `orders` is one order. A row in `order_items` is one line item. Joining them without aggregating first multiplies rows.
-- Danger: joining before knowing row shape
SELECT o.customer_id, SUM(o.amount) AS total
FROM orders o
JOIN payments p ON p.order_id = o.id -- payments has N rows per order
GROUP BY o.customer_id;-- Safe: pre-aggregate payments, then join
WITH paid AS (
SELECT order_id, SUM(amount) AS total_paid
FROM payments
GROUP BY order_id
)
SELECT o.customer_id, SUM(p.total_paid) AS total
FROM orders o
JOIN paid p ON p.order_id = o.id
GROUP BY o.customer_id;