Ver Mensaje Individual
  #2 (permalink)  
Antiguo 28/06/2013, 12:53
leonardo_josue
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 4 meses
Puntos: 447
Respuesta: INNER JOIN con tres tablas y función SUM

Hola luis_enr27:

Este problema es bastante típico, y por lo general se ocasiona porque no se tiene claro el función de los JOIN's... vayamos por partes...

Cita:
El problema es que utilizo un while para la obtencion de informacion y llenado de un reporte pero me devuelve informacion erronea cuando hago una consulta, ya que me multiplica la informacion(sumas) por el numero de registros de la tabla de union es por ello qe hago case
En este punto el problema puede estar en la cardinalidad de tus tablas, es decir cómo están relacionadas tus tablas... (puede ser 1 a 1, 1 a n o 0 a n)... el detalle al decir que te está "multiplicando" la información me hace suponer que tienes una relación 1 a n, pero la suma no la haces de manera consolidada... Veamos este ejemplo. Supongamos que tienes estos datos:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM ventas;
  2. +---------+-------+
  3. | idventa | monto |
  4. +---------+-------+
  5. |       1 |   100 |
  6. |       2 |   200 |
  7. |       3 |   300 |
  8. +---------+-------+
  9. 3 rows in set (0.00 sec)
  10.  
  11. mysql> SELECT * FROM depositos;
  12. +------------+---------+-------+
  13. | iddeposito | idventa | monto |
  14. +------------+---------+-------+
  15. |          1 |       1 |    25 |
  16. |          2 |       1 |    20 |
  17. |          3 |       2 |   100 |
  18. |          4 |       1 |    20 |
  19. |          5 |       2 |    50 |
  20. +------------+---------+-------+
  21. 5 rows in set (0.00 sec)

es decir, tres ventas con un monto y varios depósitos para cada venta a manera de abonos a la cuenta... (no uso los mismos campos que tú, pero la idea es la misma)... supongamos que quieres saber cuánto se ha depositado a cada venta... La idea es SUMAR todos los depósitos e igualarlos para cada venta, pero observa que tienes una relación 0 a n, es decir, puede haber depósitos o no para cada venta... si haces un JOIN entre las tablas, olvidándote por ahora de las sumas observa qué pasa:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM ventas
  2.     -> INNER JOIN depositos ON ventas.idventa = depositos.idventa;
  3. +---------+-------+------------+---------+-------+
  4. | idventa | monto | iddeposito | idventa | monto |
  5. +---------+-------+------------+---------+-------+
  6. |       1 |   100 |          1 |       1 |    25 |
  7. |       1 |   100 |          2 |       1 |    20 |
  8. |       2 |   200 |          3 |       2 |   100 |
  9. |       1 |   100 |          4 |       1 |    20 |
  10. |       2 |   200 |          5 |       2 |    50 |
  11. +---------+-------+------------+---------+-------+
  12. 5 rows in set (0.00 sec)

Observa en primer lugar, que por cada registro en tu tabla depósitos se está repitiendo el monto de la venta... por lo tanto, si agrupas por venta y quieres obtener el monto de la venta, pues daría la impresión de que se multiplicó... además, la venta 3 no tiene ningún depósito, por lo tanto al utilizar INNER JOIN no se presenta...

Código MySQL:
Ver original
  1. mysql> SELECT ventas.idventa,
  2.     -> SUM(ventas.monto) total_venta, SUM(depositos.monto) total_depositos
  3.     -> FROM ventas
  4.     -> INNER JOIN depositos ON ventas.idventa = depositos.idventa
  5.     -> GROUP BY ventas.idventa;
  6. +---------+-------------+-----------------+
  7. | idventa | total_venta | total_depositos |
  8. +---------+-------------+-----------------+
  9. |       1 |         300 |              65 |
  10. |       2 |         400 |             150 |
  11. +---------+-------------+-----------------+
  12. 2 rows in set (0.00 sec)

Como dije al inicio, el problema es la cardinalidad de tus tablas... debes convertir tu relación 1 a n en una relación 1 a 1... es decir, sumar primeramente todos los depósitos antes de hacer el JOIN... además, en lugar de utilizar un INNER JOIN, debes hacer uso de LEFT JOIN o RIGTH JOIN, para que las relaciones no sean obligadas. sería más o menos así:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM ventas LEFT JOIN
  2.     -> (  SELECT idventa, SUM(monto) total_depositos
  3.     ->    FROM depositos GROUP BY idventa
  4.     -> ) depositos ON ventas.idventa = depositos.idventa;
  5. +---------+-------+---------+-----------------+
  6. | idventa | monto | idventa | total_depositos |
  7. +---------+-------+---------+-----------------+
  8. |       1 |   100 |       1 |              65 |
  9. |       2 |   200 |       2 |             150 |
  10. |       3 |   300 |    NULL |            NULL |
  11. +---------+-------+---------+-----------------+
  12. 3 rows in set (0.00 sec)

de esta manera las sumas son correctas y además presenta todos los registros, no solo aquellos que tengan registros en la otra tabla...

observa que en el JOIN se hace una subconsulta, agrupando previamente. de esta manera se evita la "multiplicación" de las cantidades.

Dale un vistazo y trata de implementar este tipo de consultas a lo que quieres hacer.

Saludos
Leo.