Primero construye la suma, luego únete. Así:
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)
Tal como lo tenías, cada value_in se combinaría con cada value_out coincidente , multiplicando así los números. Debe agregar primero y luego unirse a uno en suma con uno out-sum y todo es maravilloso. ¿O lo es?
¿Qué sucede si no hay value_in? o value_out para un (date, uid) dado ? O solo value_in O simplemente value_out ? Su consulta fallará.
Mejoré usando un LEFT JOIN en lugar de [INNER] JOIN , pero lo que realmente quieres es una FULL OUTER JOIN - una de las funciones que faltan en MySQL.
Puede proporcionar una lista de días en una tabla separada y LEFT JOIN ambas tablas, o puede evitar la función que falta con dos veces LEFT JOIN y UNION . Ver aquí para un ejemplo
.
O podrías multiplicar tu value_out por -1 UNIR ambas tablas y construir una suma.
Pero tú todavía no obtendría una fila por un día sin ningún value_in o value_out , que infringe su descripción.
Entonces, la única solución limpia es tener una tabla con todos los (date, uid) desea en el resultado y LEFT JOIN las sumas de table1 y table2 a él, o UNION ALL los tres (negativo table2 ) en una subselección y luego suma.