Reputation: 9212
I have 3 tables.
table_customers - customer_id, name
table_orders - order_id, customer_id, order_datetime
table_wallet - customer_id, amount, type // type 1- credit, type 2- debit
I need to get all customers, their total balance, and their last order date and order id. This is my query.
SELECT
C.customer_id,
C.name,
COALESCE( SUM(CASE WHEN type = 2 THEN -W.amount ELSE W.amount END), 0) AS value,
COALESCE( max( O.order_id ) , '0' ) AS last_order_id,
COALESCE( max( date( O.order_datetime ) ) , '0000-00-00' ) AS last_order_date
FROM
table_customers as C
LEFT JOIN
table_wallet as W
ON C.customer_id = W.customer_id
LEFT JOIN
table_orders AS O
ON W.customer_id = O.customer_id
group by C.customer_id
ORDER BY C.customer_id
Everything is coming correct except customer's total value. From result it seems its getting added multiple times.
What is wrong in query? Can anyone help me on this?
Upvotes: 0
Views: 713
Reputation: 400
This is doing a many-to-many join on table_customers
to table_orders
, which will mess with your sums. Rather do this:
SELECT C.customer_id
, C.name
, IFNULL((SELECT SUM(IF(W.type=2, -1*W.amount, W.amount))
FROM table_wallet W
WHERE C.customer_id = W.customer_id),0) AS value
, IFNULL((SELECT MAX(DATE(O.order_id))
FROM table_orders O
WHERE C.customer_id = O.customer_id),'0') AS last_order_id
, IFNULL((SELECT MAX(DATE(O.order_datetime))
FROM table_orders O
WHERE C.customer_id = O.customer_id),'0000-00-00') AS last_order_date
FROM table_customers as C
ORDER BY C.customer_id
This will return one row per customer, then subquery the fields you want. I've substituted IFNULL
for COALESCE
as I find it cleaner, but this is a preference thing.
Upvotes: 1