I have these two tables
table1 : date | uid | value_in
table2 : date | uid | value_out
each day, every uid will receive a balance value for both in and out, regardless of the number of transaction/records
what I want to do is to combine the query result to be like this
date | uid | value_in | value_out | (value_in-value_out) as balance
however, when I do this query
SELECT
a.date,
a.uid,
SUM(a.value_in),
SUM(b.value_out),
(SUM(a.value_in)-SUM(b.value_out)) AS balance
FROM table1 a
INNER JOIN table2 b ON a.date=b.date AND a.uid=b.uid
GROUP BY a.date, a.uid
it produce invalid result (the SUM is doubled or tripled)
how should I modify my query so it does not produce doubled result ?
First build the sum, then join. Like this:
The way you had it, every
value_inwould be combined with every matchingvalue_out, thereby multiplying the numbers. You must aggregate first and then you join one in-sum with one out-sum and everything is groovy. Or is it?What happens if there are no
value_inorvalue_outfor a given(date, uid)? Or onlyvalue_inOr justvalue_out? Your query will fail.I improved by using a
LEFT JOINinstead of[INNER] JOIN, but what you really want is aFULL OUTER JOIN– one of the missing features in MySQL.You can either provide a list of days in a separate table and
LEFT JOINboth tables to it, or you can work around the missing feature with two timesLEFT JOINandUNION. See here for an example.Or you could multiply your
value_outby-1UNION both tables together and build one sum.But you still would not get a row for a day without any
value_inorvalue_out, which violates your description.So, the only clean solution is to have a table with all
(date, uid)you want in the result andLEFT JOINthe sums oftable1andtable2to it, orUNION ALLthe three (negativetable2) in a sub-select and then sum up.