Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Como evitar un producto cartesiano en consulta entre 3 tablas

Estas en el tema de Como evitar un producto cartesiano en consulta entre 3 tablas en el foro de Mysql en Foros del Web. Cordial saludo, tengo el siguiente inconveniente con una consulta a tres tablas la cual me da como resultado un producto cartesiano(muestra datos repetidos) aquí el ...
  #1 (permalink)  
Antiguo 31/07/2017, 12:57
Avatar de heberthm  
Fecha de Ingreso: noviembre-2013
Ubicación: Cali
Mensajes: 65
Antigüedad: 11 años
Puntos: 1
Pregunta Como evitar un producto cartesiano en consulta entre 3 tablas

Cordial saludo, tengo el siguiente inconveniente con una consulta a tres tablas la cual me da como resultado un producto cartesiano(muestra datos repetidos) aquí el código:

SELECT C.cedula, C.nombre, C.apellido1, C.apellido2, V.cedula, V.id,
V.vacunas, V.no_dosis, V.fecha, M.nombre_mascota, M.cedula
FROM clientes C
INNER JOIN mascotas M ON C.cedula = M.cedula
INNER JOIN vacunas V ON C.cedula = V.cedula
WHERE M.cedula = C.cedula

Qué debo cambiar para evitar que se muestren datos repetidos?.
De antemano gracias.
__________________
Hebeth Mazuera
  #2 (permalink)  
Antiguo 31/07/2017, 13:33
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 18 años, 3 meses
Puntos: 774
Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

No creo que se traten de datos repetidos sino que la relacion que tienes en tus tablas es de 1 a muchos, por ejemplo creo que un cliente puede tener mas de una mascota y una mascota puede tener mas de una vacuna cierto? ahora para evitar eso trata de filtrar mejor tus datos, como haces esto, fijate en que parte se duplican los resultados y mete un filtro ahi, te recomiendo hacer la consulta por partes, primero la de clientes con mascotas, revisa los resultados y ve si nada mas es un resultado por cada cliente-mascota, si no es asi ve cual podria ser un campo discriminante y agregalo en tu where, ya que tengas bien eso agrega la siguiente tabla y repite el procedimiento.....
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #3 (permalink)  
Antiguo 31/07/2017, 13:53
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 10 meses
Puntos: 447
Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

Hola heberthm:

No nos pones datos de ejemplo de tus tablas, pero mucho ojo, el que tu consulta muestre datos "repetidos" no necesariamente significa que se esté realizando un producto cartesiano...

lo primero que debes verificar es cuál es la cardinalidad entre tus tablas, si por ejemplo, tienes una relación 1 a 1, entonces una manera de verificar el si se está realizando un producto cartesiano es contando el número de registro que aparecen en la consulta final, el número de registros NO DEBE SER MAYOR AL NÚMERO DE REGISTROS EN CUALQUIERA DE TUS TABLAS. Checa este ejemplo:

Código SQL:
Ver original
  1. mysql> SELECT *
  2.     -> FROM tabla_1;
  3. +-----------+-------------+
  4. | id_tabla1 | descripcion |
  5. +-----------+-------------+
  6. |         1 | uno         |
  7. |         2 | dos         |
  8. |         3 | tres        |
  9. +-----------+-------------+
  10. 3 ROWS IN SET (0.00 sec)
  11.  
  12. mysql> SELECT *
  13.     -> FROM tabla_2;
  14. +-----------+-------------+
  15. | id_tabla2 | descripcion |
  16. +-----------+-------------+
  17. |         1 | one         |
  18. |         2 | two         |
  19. |         3 | three       |
  20. +-----------+-------------+
  21. 3 ROWS IN SET (0.00 sec)
  22.  
  23. mysql> SELECT * FROM tabla_1
  24.     -> INNER JOIN tabla_2 ON tabla_1.id_tabla1 = tabla_2.id_tabla2;
  25. +-----------+-------------+-----------+-------------+
  26. | id_tabla1 | descripcion | id_tabla2 | descripcion |
  27. +-----------+-------------+-----------+-------------+
  28. |         1 | uno         |         1 | one         |
  29. |         2 | dos         |         2 | two         |
  30. |         3 | tres        |         3 | three       |
  31. +-----------+-------------+-----------+-------------+
  32. 3 ROWS IN SET (0.00 sec)

Sin embargo, si tienes una relación 1 a muchos, puedes tener INFORMACIÓN "REPETIDA" pero esto no quiere decir que se esté haciendo un producto cartesiano, checa este ejemplo:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla_1;
  2. +-----------+-------------+
  3. | id_tabla1 | descripcion |
  4. +-----------+-------------+
  5. |         1 | uno         |
  6. |         2 | dos         |
  7. |         3 | tres        |
  8. +-----------+-------------+
  9. 3 rows in set (0.00 sec)
  10.  
  11. mysql> SELECT * FROM tabla_2;
  12. +-----------+-------------+
  13. | id_tabla2 | descripcion |
  14. +-----------+-------------+
  15. |         1 | one         |
  16. |         1 | un          |
  17. |         1 | eins        |
  18. |         2 | two         |
  19. |         2 | deux        |
  20. |         2 | zwei        |
  21. |         3 | three       |
  22. |         3 | trois       |
  23. |         3 | drei        |
  24. +-----------+-------------+
  25. 9 rows in set (0.00 sec)
  26.  
  27. mysql> SELECT * FROM tabla_1
  28.     -> INNER JOIN tabla_2 on tabla_1.id_tabla1 = tabla_2.id_tabla2;
  29. +-----------+-------------+-----------+-------------+
  30. | id_tabla1 | descripcion | id_tabla2 | descripcion |
  31. +-----------+-------------+-----------+-------------+
  32. |         1 | uno         |         1 | one         |
  33. |         1 | uno         |         1 | un          |
  34. |         1 | uno         |         1 | eins        |
  35. |         2 | dos         |         2 | two         |
  36. |         2 | dos         |         2 | deux        |
  37. |         2 | dos         |         2 | zwei        |
  38. |         3 | tres        |         3 | three       |
  39. |         3 | tres        |         3 | trois       |
  40. |         3 | tres        |         3 | drei        |
  41. +-----------+-------------+-----------+-------------+
  42. 9 rows in set (0.00 sec)

en este caso, las descripciones en español se están "repitiendo", pero esto no quiere decir que entre las tablas haya un PRODUCTO CARTESIANO, sino que esto es perfectamente normal debido a que hay una relación 1 a muchos entre las tablas...

entonces, ¿cuando ocurre un producto cartesiano? cuando un registro de una tabla se "combina" o se relaciona CON TODOS LOS REGISTROS DE OTRA TABLA... haya o no haya una relación entre ellos... es decir, algo así:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla_1
  2.     -> INNER JOIN tabla_2;
  3. +-----------+-------------+-----------+-------------+
  4. | id_tabla1 | descripcion | id_tabla2 | descripcion |
  5. +-----------+-------------+-----------+-------------+
  6. |         1 | uno         |         1 | one         |
  7. |         2 | dos         |         1 | one         |
  8. |         3 | tres        |         1 | one         |
  9. |         1 | uno         |         1 | un          |
  10. |         2 | dos         |         1 | un          |
  11. |         3 | tres        |         1 | un          |
  12. |         1 | uno         |         1 | eins        |
  13. |         2 | dos         |         1 | eins        |
  14. |         3 | tres        |         1 | eins        |
  15. |         1 | uno         |         2 | two         |
  16. |         2 | dos         |         2 | two         |
  17. |         3 | tres        |         2 | two         |
  18. |         1 | uno         |         2 | deux        |
  19. |         2 | dos         |         2 | deux        |
  20. |         3 | tres        |         2 | deux        |
  21. |         1 | uno         |         2 | zwei        |
  22. |         2 | dos         |         2 | zwei        |
  23. |         3 | tres        |         2 | zwei        |
  24. |         1 | uno         |         3 | three       |
  25. |         2 | dos         |         3 | three       |
  26. |         3 | tres        |         3 | three       |
  27. |         1 | uno         |         2 | trois       |
  28. |         2 | dos         |         2 | trois       |
  29. |         3 | tres        |         2 | trois       |
  30. |         1 | uno         |         3 | drei        |
  31. |         2 | dos         |         3 | drei        |
  32. |         3 | tres        |         3 | drei        |
  33. +-----------+-------------+-----------+-------------+
  34. 27 rows in set (0.00 sec)

esto SI ES UN PRODUCTO CARTESIANO.

Postea algunos datos de ejemplo de tus tablas para poder revisar.

Saludos
Leo.
  #4 (permalink)  
Antiguo 31/07/2017, 13:55
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 10 meses
Puntos: 447
Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

Jejejejeje, Libras tomó la delantera con la respuesta

Saludos
Leo.
  #5 (permalink)  
Antiguo 31/07/2017, 15:04
Avatar de heberthm  
Fecha de Ingreso: noviembre-2013
Ubicación: Cali
Mensajes: 65
Antigüedad: 11 años
Puntos: 1
Pregunta Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

Gracias a leonardo_josue y a libras por contestar a mi pregunta. A continuación imágenes de las tablas que utilizo y de la consulta realizada sobre dichas tablas:


Tabla cliente
http://i.imgur.com/ZJEl2CX.png

Tabla mascotas
http://i.imgur.com/CxjdMzx.png

Tabla vacunas
http://i.imgur.com/Njw0syp.png


Imagen de la consulta:
http://i.imgur.com/6DVe7wP.png
__________________
Hebeth Mazuera
  #6 (permalink)  
Antiguo 31/07/2017, 15:31
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 18 años, 3 meses
Puntos: 774
Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

como te dije ahi no hay datos repetidos, se ven los datos bien, un cliente tiene mas de una mascota y la mascota tiene mas de una vacuna, que es lo que quieres mostrar con esa consulta??
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #7 (permalink)  
Antiguo 31/07/2017, 16:29
Avatar de heberthm  
Fecha de Ingreso: noviembre-2013
Ubicación: Cali
Mensajes: 65
Antigüedad: 11 años
Puntos: 1
Pregunta Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

Libras, te muestro los datos que contienen mis tablas:

Tabla clientes
http://i.imgur.com/Hfqm3O5.png

Tabla mascotas
http://i.imgur.com/hj3ZEM4.png


Tabla vacunas
http://i.imgur.com/UDEQbCt.png

Si observas la tabla vacunas tiene 7 registros y al realizar la consulta me crea un listado con 14 registros como se ve en la siguiente imagen:

http://i.imgur.com/65XcTZ8.png

Se están duplicando los valores de la tabla vacunas de 7 a 14 registros.

Lo que deseo hacer es poder mostrar el listado de vacunas con los campos
cédula, nombre, apellido1, apellido2 (de la tabla cliente)
nombre_mascota y edad (de la tabla mascotas) y
vacuna y No_dosis (de la tabla vacunas) de esta forma resulta una consulta SQL a tres tablas.
__________________
Hebeth Mazuera
  #8 (permalink)  
Antiguo 01/08/2017, 07:47
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 18 años, 3 meses
Puntos: 774
Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

No se estan duplicando los valores, ni se estan repitiendo, mira en la tabla mascotas tienes 2 registros con la cedula 111 111, ahora en la tabla vacunas tienes 7 registros con la cedula 111 111, ahora al hacer el join por cada registro de mascota 111 111, corresponde un registro de vacuna, entonces 2 * 7=14, el resultado de la consulta esta bien segun los datos que tienes, con esos datos te puede decir que a Gyna y a Sirope se les han administrado 7 vacunas a cada uno eso es cierto, si no es correcto entonces ocupas acomodar tu informacion desde las tablas, pues el query va a regresar lo que tengas en ells
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #9 (permalink)  
Antiguo 01/08/2017, 17:20
Avatar de heberthm  
Fecha de Ingreso: noviembre-2013
Ubicación: Cali
Mensajes: 65
Antigüedad: 11 años
Puntos: 1
Respuesta: Como evitar un producto cartesiano en consulta entre 3 tablas

Gracias libras por la colaboración ya comprendí el resultado de mi consulta
__________________
Hebeth Mazuera

Etiquetas: producto, select, tabla, tablas
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:15.