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

[SOLUCIONADO] Join 4 tablas

Estas en el tema de Join 4 tablas en el foro de Mysql en Foros del Web. Saludos cordiales, Tengo 4 tablas: (pongo los campos relevantes) Productos producto_id,descripcion,activo Productos_a_subcategias id,producto_id,subcategoria_id comentarios id,producto_id votos id,producto_id Lo que hago ahora: Selecciono todos los productos ...
  #1 (permalink)  
Antiguo 27/11/2014, 11:42
 
Fecha de Ingreso: enero-2008
Ubicación: Málaga - España
Mensajes: 346
Antigüedad: 16 años, 3 meses
Puntos: 13
Join 4 tablas

Saludos cordiales,
Tengo 4 tablas: (pongo los campos relevantes)

Productos
producto_id,descripcion,activo

Productos_a_subcategias
id,producto_id,subcategoria_id

comentarios
id,producto_id

votos
id,producto_id

Lo que hago ahora:
Selecciono todos los productos de la tabla productos que esten condicionados con la subcategoria a la que pertenece

Código MySQL:
Ver original
  1. SELECT * FROM productos p
  2. INNER JOIN productos_a_subcategorias pas ON p.producto_id = pas.producto_id
  3. WHERE pas.subcategoria_id = 27 AND p.activo = TRUE

Despues, pues en programacion, recorro el recordset y para cada uno de los productos, hago la media de los votos:

Código MySQL:
Ver original
  1. SELECT AVG(voto) as media_votos FROM valoracion_producto WHERE producto_ID = 1

Y tambien cuento la cantidad de comentarios que tiene cada uno:

Código MySQL:
Ver original
  1. Select COUNT(*) from opiniones Where id_producto = 1

Esto creo que es malgastar recursos del servidor, ademas de que asi, no puedo ordenar los resultados, por ejemplo, por producto mas comentado o mas valorado.

Y he probado haciendo algunas pruebas con INNER JOIN, LEFT JOIN, pero mis conocimientos son basicos y no me aclaro.
Esto es lo que llevo ahora, pero no funciona bien :(

Código MySQL:
Ver original
  1. SELECT * FROM productos p
  2. INNER JOIN productos_a_subcategorias pas ON p.producto_id = pas.producto_id AND pas.subcategoria_id = 27 AND p.activo = TRUE
  3. LEFT JOIN (SELECT id_producto opi_id_producto,activo opi_act,COUNT(*) total_opiniones FROM opiniones ) opi ON p.producto_id = opi.opi_id_producto AND opi.opi_act = TRUE
  4. LEFT JOIN (SELECT producto_id voto_producto_id,AVG(voto) as voto_media_votos FROM valoracion_producto) voto ON p.producto_id = voto.voto_producto_id

Alguna ayuda me vendrá genial, llevo dos dias haciendo pruebas, pero no doy con la tecla.
  #2 (permalink)  
Antiguo 27/11/2014, 15:52
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Join 4 tablas

Hola alpe2000:

En realidad no estás tan alejado de la respuesta, sin embargo tienes algunos detalles a considerar:

1. en las cláusulas ON, es recomendable que sólo utilices aquellas condiciones que involucran a las llaves de las tablas, las condiciones para filtrar la información debes colocarlas en la sección WHERE.
2. Tienes un problema con las subconsultas, ya que NO ESTÁS AGRUPANDO POR PRODUCTO, por lo tanto, tanto el promedio como el conteo están arrojando un resultado general, no particular para un producto.

No es lo mismo poner esto:

Código MySQL:
Ver original
  1. SELECT id_producto opi_id_producto, activo opi_act, COUNT(*) total_opiniones
  2. FROM opiniones

a poner esto:

Código MySQL:
Ver original
  1. SELECT id_producto opi_id_producto, activo opi_act, COUNT(*) total_opiniones
  2. FROM opiniones
  3. GROUP BY id_producto opi_id_producto, activo opi_act

3. Evita el uso de SELECT *, esto tiene un pésimo rendimiento... aun cuando necesites TODOS los campos de una tabla (que es un caso poco común), es mejor que listes todos y cada uno de los campos.

El resto parece estar en orden, pero veamos si te queda más claro con este ejemplo.

Supongamos que tienes las siguientes tablas:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM productos;
  2. +-------------+-----------------+
  3. | id_producto | descripcion     |
  4. +-------------+-----------------+
  5. |           1 | producto uno    |
  6. |           2 | producto dos    |
  7. |           3 | producto tres   |
  8. |           4 | producto cuatro |
  9. +-------------+-----------------+
  10. 4 rows in set (0.00 sec)
  11.  
  12.  
  13. mysql> SELECT * FROM votos;
  14. +---------+-------------+------+
  15. | id_voto | id_producto | voto |
  16. +---------+-------------+------+
  17. |       1 |           1 |   10 |
  18. |       2 |           1 |    9 |
  19. |       3 |           1 |   10 |
  20. |       4 |           2 |    7 |
  21. |       5 |           2 |    9 |
  22. +---------+-------------+------+
  23. 5 rows in set (0.00 sec)
  24.  
  25. mysql> SELECT * FROM comentarios;
  26. +---------------+-------------+----------------+
  27. | id_comentario | id_producto | comentario     |
  28. +---------------+-------------+----------------+
  29. |             1 |           1 | comentario 1.1 |
  30. |             2 |           1 | comentario 1.2 |
  31. |             3 |           3 | comentario 3.1 |
  32. +---------------+-------------+----------------+
  33. 3 rows in set (0.00 sec)

es decir, tienes cuatro productos:
  • el producto UNO tiene comentarios y votos
  • el producto DOS solo tiene votos, pero no tiene comentarios
  • el producto TRES solo tiene comentarios, pero no tiene votos
  • el producto CUATRO no tiene ni comentarios ni votos

Ahora, para obtener el PROMEDIO de votos y el CONTEO de comentarios, tienes que hacer uso de las funciones de agrupación PERO UTILIZAR EL GROUP BY:

Código MySQL:
Ver original
  1. mysql> SELECT id_producto, AVG(voto) promedio_votos
  2.     -> FROM votos
  3.     -> GROUP BY id_producto;
  4. +-------------+----------------+
  5. | id_producto | promedio_votos |
  6. +-------------+----------------+
  7. |           1 |         9.6667 |
  8. |           2 |         8.0000 |
  9. +-------------+----------------+
  10. 2 rows in set (0.00 sec)
  11.  
  12. mysql> SELECT id_producto, COUNT(id_producto) total_comentarios
  13.     -> FROM comentarios
  14.     -> GROUP BY id_producto;
  15. +-------------+-------------------+
  16. | id_producto | total_comentarios |
  17. +-------------+-------------------+
  18. |           1 |                 2 |
  19. |           3 |                 1 |
  20. +-------------+-------------------+
  21. 2 rows in set (0.00 sec)

Entonces si, puedes hacer los LEFT JOIN'S para asociar estas cantidades a sus productos:

Código MySQL:
Ver original
  1. mysql> SELECT p.id_producto, p.descripcion, v.promedio_votos, c.total_comentarios
  2.     -> FROM productos p
  3.     -> LEFT JOIN ( SELECT id_producto, AVG(voto) promedio_votos
  4.     ->             FROM votos
  5.     ->             GROUP BY id_producto) v ON v.id_producto = p.id_producto
  6.     -> LEFT JOIN ( SELECT id_producto, COUNT(id_producto) total_comentarios
  7.     ->             FROM comentarios
  8.     ->             GROUP BY id_producto) c ON c.id_producto = p.id_producto;
  9. +-------------+-----------------+----------------+-------------------+
  10. | id_producto | descripcion     | promedio_votos | total_comentarios |
  11. +-------------+-----------------+----------------+-------------------+
  12. |           1 | producto uno    |         9.6667 |                 2 |
  13. |           3 | producto tres   |           NULL |                 1 |
  14. |           2 | producto dos    |         8.0000 |              NULL |
  15. |           4 | producto cuatro |           NULL |              NULL |
  16. +-------------+-----------------+----------------+-------------------+
  17. 4 rows in set (0.00 sec)

Haz los ajustes que te comento y si continuas con problemas, postea algunos datos de ejemplo de tus tablas y dinos en qué está fallando tu consulta.

Saludos
Leo
  #3 (permalink)  
Antiguo 01/12/2014, 06:17
 
Fecha de Ingreso: enero-2008
Ubicación: Málaga - España
Mensajes: 346
Antigüedad: 16 años, 3 meses
Puntos: 13
Respuesta: Join 4 tablas

:D :D :D

Todo perfecto EL GROUP BY era la clave, mis pobres conocimientos no llegaban, jajjaja. Muchas gracias.
Así me quedó la sentencia despues de agregar la tabla Productos_a_subcategias

Código MySQL:
Ver original
  1. SELECT p.producto_id, p.descripcion, p.precio, p.referencia, p.vistojsg, v.promedio_votos, c.total_comentarios FROM productos p
  2. LEFT JOIN ( SELECT producto_id, AVG(voto) promedio_votos FROM valoracion_producto GROUP BY producto_id) v
  3.     ON v.producto_id = p.producto_id
  4. LEFT JOIN ( SELECT id_producto, COUNT(id_producto) total_comentarios FROM opiniones GROUP BY id_producto) c
  5.     ON c.id_producto = p.producto_id
  6. INNER JOIN productos_a_subcategorias pas ON p.producto_id = pas.producto_id
  7. WHERE pas.subcategoria_id = "& subcategoria_id &" AND p.activo = TRUE
  8. ORDER BY " & session("orden")

Le paso las variables de subcategoria segun la subcategoria que quiera mostrar y el orden segun las preferencias del usuario, y todo funciona correcto.
MIL GRACIAS

Etiquetas: campo, join, 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 15:55.