I've got four MySQL tables: contacts, orders, ordered_products and products and I'm trying to write some reporting queries. Here's one of them:
SELECT t1.name, t1.contact_id, SUM(t1.prodSoldQty) AS contactSoldQty, SUM(t1.prodSoldVol) AS soldVol
FROM contacts
INNER JOIN
(
SELECT
contacts.name,
ordered_products.product_id,
ordered_products.contact_id,
SUM(ordered_products.quantity) AS prodSoldQty,
(products.price * SUM(ordered_products.quantity)) AS prodSoldVol
FROM ordered_products
INNER JOIN contacts ON contacts.id = ordered_products.contact_id
INNER JOIN products ON products.id = ordered_products.product_id
INNER JOIN orders ON orders.id = ordered_products.order_id
GROUP BY ordered_products.product_id , ordered_products.contact_id
ORDER BY ordered_products.product_id
) AS t1 ON t1.contact_id = contacts.id
GROUP BY contacts.id
ORDER BY t1.name;
Everything works as expected, albeit if I add (and I need to add) another [LEFT|INNER] JOIN (for example: INNER JOIN orders ON orders.contact_id = contacts.id) the rows SUM totals got messed up (they seems to duplicate, triplicate ... accordingly to the number of the orders). I guess the problem might be the multiple grouping in the first join derived table. Yet it eludes me. Here you can find a slightly variant of the above query. Even this tiny modification is able to trigger the 'issue':
SELECT t1.name, t1.contact_id,
SUM(t1.prodSoldQty) AS contactSoldQty,
SUM(t1.prodSoldVol) AS soldVol
FROM contacts
INNER JOIN
(
SELECT
contacts.name,
ordered_products.product_id,
ordered_products.contact_id,
SUM(ordered_products.quantity) AS prodSoldQty,
(products.price * SUM(ordered_products.quantity)) AS prodSoldVol
FROM ordered_products
INNER JOIN contacts ON contacts.id = ordered_products.contact_id
INNER JOIN products ON products.id = ordered_products.product_id
INNER JOIN orders ON orders.id = ordered_products.order_id
GROUP BY ordered_products.product_id , ordered_products.contact_id
ORDER BY ordered_products.product_id
) AS t1 ON t1.contact_id = contacts.id
INNER JOIN orders ON orders.contact_id = contacts.id
WHERE orders.order_state_id != '111'
GROUP BY contacts.id
ORDER BY t1.name;
The above path is a dead end. With the help from @Gordon Linoff I was able to find a better way. One of the reporting goal was to calculate total product cost amount & total product selling amount on a customer/contact base. I was focused on doing that with two separate join. It seems that one will suffice (avoidig including several times nearly the same tables):
SELECT t1.name, t1.contact_id,
SUM(t1.prodSellQty) AS sellQty,
SUM(t1.prodCostVol) AS costAmount,
SUM(t1.prodSellVol) AS sellAmount
FROM contacts
INNER JOIN
(
SELECT
contacts.name,
ordered_products.contact_id,
SUM(ordered_products.quantity) AS prodSellQty,
SUM(products.price * ordered_products.quantity) AS prodCostVol,
SUM(ordered_products.price * ordered_products.quantity) AS prodSellVol
FROM ordered_products
INNER JOIN contacts ON contacts.id = ordered_products.contact_id
INNER JOIN products ON products.id = ordered_products.product_id
INNER JOIN orders ON orders.id = ordered_products.order_id
GROUP BY ordered_products.product_id , ordered_products.contact_id
ORDER BY ordered_products.product_id
) AS t1 ON t1.contact_id = contacts.id
GROUP BY contacts.id
ORDER BY contacts.name;
Thanks, Luca