Byg først summen, kom så med. Sådan:
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)
Som du havde det, hver value_in
ville blive kombineret med hver matchende value_out
, hvorved tallene ganges. Du skal først samle og derefter tilslutte dig én i-sum med én out-sum og alt er groovy. Eller er det?
Hvad sker der, hvis der ikke er nogen value_in
eller value_out
for en given (date, uid)
? Eller kun value_in
Eller bare value_out
? Din forespørgsel vil mislykkes.
Jeg forbedrede mig ved at bruge en LEFT JOIN
i stedet for [INNER] JOIN
, men hvad du virkelig ønsker, er en FULL OUTER JOIN
- en af de manglende funktioner i MySQL.
Du kan enten angive en liste over dage i en separat tabel og LEFT JOIN
begge tabeller til det, eller du kan omgå den manglende funktion med to gange LEFT JOIN
og UNION
. Se her for et eksempel
.
Eller du kan gange din value_out
med -1
FORBIND begge tabeller sammen og byg en sum.
Men du stadig ville ikke få en række i en dag uden nogen value_in
eller value_out
, hvilket overtræder din beskrivelse.
Så den eneste rene løsning er at have en tabel med alle (date, uid)
du vil have i resultatet og LEFT JOIN
summen af table1
og table2
til det, eller UNION ALL
de tre (negativ table2
) i et undervalg og opsummer derefter.