Construisez d'abord la somme, puis joignez-vous. Comme ceci :
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)
Comme vous l'aviez, chaque value_in
serait combiné avec chaque value_out
correspondant , multipliant ainsi les nombres. Vous devez d'abord agréger, puis rejoindre un en somme avec un out-sum et tout est groovy. Ou est-ce ?
Que se passe-t-il s'il n'y a pas de value_in
ou value_out
pour un (date, uid)
donné ? Ou seulement value_in
Ou juste value_out
? Votre requête échouera.
J'ai amélioré en utilisant un LEFT JOIN
au lieu de [INNER] JOIN
, mais ce que vous voulez vraiment, c'est un FULL OUTER JOIN
- une des fonctionnalités manquantes dans MySQL.
Vous pouvez soit fournir une liste de jours dans un tableau séparé et LEFT JOIN
les deux tables, ou vous pouvez contourner la fonctionnalité manquante avec deux fois LEFT JOIN
et UNION
. Voir ici pour un exemple
.
Ou vous pouvez multiplier votre value_out
par -1
UNION les deux tables ensemble et construisez une somme.
Mais vous toujours n'obtiendrait pas une ligne pendant une journée sans aucun value_in
ou value_out
, ce qui ne respecte pas votre description.
Donc, la seule solution propre est d'avoir une table avec tous les (date, uid)
vous voulez dans le résultat et LEFT JOIN
les sommes de table1
et table2
ou UNION ALL
les trois (négatif table2
) dans une sous-sélection puis résumer.