Mira, lo primero que tienes que tratar de hacer es ordenar la consulta, porque así como la escribes es inentendible.
Primero estructuremos la cosa:
Código MySQL:
Ver original publicaciones.*,
tipopublicaciones.destagen,
tipopublicaciones.destasec,
provincias.nombre
as nompro
, localidades.nombre
as nomloc
, usuarios.usuario
as codusu
, usuarios.nombre
as nomusu
, tipomonedas.simbolo
as moneda
, tipoarticulos.nombre
as nomtar
, publicaciones.cantidad
-sum(if(compras.cantidad
is not null,compras.cantidad
,0)) as quedan
, sum(if(tipomovimientos.signo
='+', importe
,if(tipomovimientos.signo
='-',importe
*-1,0))) as saldo
publicaciones
left join tipopublicaciones
on tipopublicaciones.idtipopublicacion
=publicaciones.idtipopublicacion
left join usuarios
on usuarios.idusuario
= publicaciones.idusuario
left join tipomonedas
on tipomonedas.idtipomoneda
= publicaciones.idtipomoneda
left join tipoarticulos
on tipoarticulos.idtipoarticulo
=publicaciones.idtipoarticulo
left join paises
on paises.idpais
=publicaciones.idpais
left join provincias
on provincias.idprovincia
=publicaciones.idprovincia
left join localidades
on localidades.idlocalidad
=publicaciones.idlocalidad
left join compras
on compras.idpublicacion
=publicaciones.idpublicacion
left join cuentacorriente
on cuentacorriente.idusuario
=publicaciones.idusuario
left join tipomovimientos
on tipomovimientos.idtipomovimiento
=cuentacorriente.idtipomovimiento
Aquí lo que se ve es que no has aprendido a usar alias para tablas, por lo que resulta algo difícil seguir la lógica aplicada.
Depuremos:
Código MySQL:
Ver original P.*,
TP.destagen,
TP.destasec,
PA.nombre nompai,
PR.nombre nompro,
LC.nombre nomloc,
US.usuario codusu,
US.nombre nomusu,
TM.simbolo moneda,
TA.nombre nomtar,
SUM(IF(TM.signo
='+', importe
, IF(TM.signo
= '-',importe
* - 1, 0))) saldo
publicaciones P
LEFT JOIN tipopublicaciones TP
ON P.idtipopublicacion
= TP.idtipopublicacion
LEFT JOIN usuarios US
ON P.idusuario
= US.idusuario
LEFT JOIN tipomonedas TM
ON P.idtipomoneda
= TM.idtipomoneda
LEFT JOIN tipoarticulos TA
ON P.idtipoarticulo
= TA.idtipoarticulo
LEFT JOIN provincias PR
ON P.idprovincia
= PR.idprovincia
LEFT JOIN localidades LC
ON P.idlocalidad
= LC.idlocalidad
LEFT JOIN compras CO
ON P.idpublicacion
= CO.idpublicacion
LEFT JOIN cuentacorriente CC
ON P.idusuario
= CC.idusuario
LEFT JOIN tipomovimientos TM
ON CC.idtipomovimiento
= TM.idtipomovimiento
Ahora podemos mirar un poco mejor lo que hay.
Lo primero que se puede observar es que estás definiendo todas las relaciones como
opcionales, es decir, lo único seguro es que existe una publicación, que
puede tener un tipo,
puede corresponder a un usuario,
puede tener un precio expresado en un tipo de moneda,
puede tener un tipo de articulo, etc.
¿Realmente son todas opcionales? ¿No hay ninguna mandatoria?
Pregunto porque las mandatorias (obligatorias) se plantean con INNER JOIN, y no con LEFT JOIN. Eso simplifica mucho la consulta.
Por otro lado, en tu esquema original estás poniendo mal el ON de las tablas. Cuando usas el LEFT JOIN debes poner primero la tabla base (la que no es nula jamás) y luego la dependiente. En este caso el orden de los factores si altera el producto.
Además de eso, estás agrupando por un sólo campo, cuando en realidad deberías agrupar por todos los que no están afectados por la función (SUM()).
Si bien MySQL admite que se agrume por menos campos que los no afectados por funciones, eso si lo haces el resultado puede ser errático, ya que en los otros campos sólo dejará el primer valor que encuentre en el primer registro, escondiendo cualquier otro tipo de agrupamiento.
Finalmente, las sumas como las estás planteando, no están bien hechas. al menos en un caso estás sumando un valor simple contra el de un agrupamiento, con lo que la operación aritmética puede estar generando (y eso creo que es lo que te pasa) un
producto cartesiano. Es decir: Está aplicando la suma a cada uno de los registros que suma, y no al total.
En esencia, lo que te conviene hacer es que el cálculo de suma se haga en una subconsulta que devuelva una tabla virtual en el FROM, y luego con esa tabla derivada haces el resto de los JOIN.
¿Se entiende la idea?