Bouw eerst de som op en doe dan mee. Zoals dit:
SELECT i.uid
,i.date
,i.v_in
,COALESCE(o.v_out, 0) AS v_out
,(i.v_in - COALESCE(o.v_out, 0)) AS balance
FROM (
SELECT date
,uid
,SUM(value_in) AS v_in
FROM table1
GROUP BY 1,2
) i
LEFT JOIN (
SELECT date
,uid
,SUM(value_out) AS v_out
FROM table2
GROUP BY 1,2
) o USING (date, uid)
Zoals je het had, elke value_in
zou worden gecombineerd met elke overeenkomende value_out
, waardoor de getallen worden vermenigvuldigd. Je moet eerst verzamelen en dan sluit je je aan bij one in totaal met één out-sum en alles is groovy. Of toch?
Wat gebeurt er als er geen value_in
. zijn of value_out
voor een gegeven (date, uid)
? Of alleen value_in
Of gewoon value_out
? Uw zoekopdracht zal mislukken.
Ik ben verbeterd door een LEFT JOIN
. te gebruiken in plaats van [INNER] JOIN
, maar wat je echt wilt is een FULL OUTER JOIN
- een van de ontbrekende functies in MySQL.
U kunt ofwel een lijst met dagen in een aparte tabel opgeven en LEFT JOIN
beide tabellen, of je kunt de ontbrekende functie omzeilen met twee keer LEFT JOIN
en UNION
. Zie hier voor een voorbeeld
.
Of je zou je value_out
kunnen vermenigvuldigen door -1
UNION beide tabellen samen en bouw één som.
Maar jij nog zou een dag geen rij krijgen zonder value_in
of value_out
, wat in strijd is met uw beschrijving.
Dus de enige schone oplossing is om een tabel te hebben met allemaal (date, uid)
je wilt in het resultaat en LEFT JOIN
de sommen van table1
en table2
ernaartoe, of UNION ALL
de drie (negatieve table2
) in een subselectie en vervolgens optellen.