Ver Mensaje Individual
  #5 (permalink)  
Antiguo 19/01/2011, 02:59
quimfv
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: INNER JOIN con tres tablas y función SUM

Veo que has entendido perfectamente la consulta. Parece compleja pero no lo es.

Para resolver una consulta de este tipo debes aplicar el principio de "divide y vencerás".

Tu pedías

1. Una lista de todos los artículos --> artículos LEFT JOIN ...
2. Una imagen por articulo, concretamente, la imagen con el id mas pequeño de cada articulo. Aquí hay que hacer una doble subconsulta, primero obtener el id de imagen mas pequeño para cada articulo y a partir de este el nombre de la imagen. --> idarticulo,imagen FROM imagenes INNER JOIN (MIN(idArticulo) From imagenes GROUP BY idarticulo) ON idimagen=MIN(idimagen)
Con el INNER JOIN consigo que solo me de el idArticulo y nombreimagen de los idMinimos, si un articulo no tiene imagen no sale en esta subconsulta
3.Un número de visitas por artículo. Estadísticas por articulo --> idarticulo,SUM(visitas) FROM estadistica GROUP BY idarticulo, si un articulo no tiene visitas no sale en esta subconsulta

Como en los tres puntos tengo idArticulo es fácil armar la consulta final jugando con los alias y con LEFT JOIN para que aparezcan todos los artículos de la tabla artículos independientemente de si tienen o no imagen y/o visitas.

Finalmente los IFNULL() tienen una función estética.

Cada una de las partes se pueden ejecutar independientemente, luego es fácil comprobar si dan lo que buscas


Por que falla la vuestra

La cardinalidad de las tablas no es la misma

TablaArticulos tiene n registros (los queremos todos)
LEF JOIN (correcto)
TablaImagenes tiene x imágenes * m artículos (no coincide ni el numero de artículos, además pueden estar repetidos) digamos que tiene i registros
LEFT JOIN
TablaEstadisticas tiene y fechas * m artículos (lo mismo) digamos que tiene e registros

luego la consulta nos dará potencialmente i*e registros todos los de artículos combinados por idart con TODOS los de imágenes (i) y estos combinados con TODOS los de estadísticas (e). Si ademas n fuera mayor que el mayor de i o e tendriamos que sumar el numero de articulos restante.

Como hacéis el group by se reduce a n registros, el MIN(idimagen) funciona puesto que el mínimo es el mínimo pero el SUM(visitas) suma todas las repeticiones que haya (i*e).

Por otro lado intentáis obtener el nombre de la imagen directamente, eso es imposible ya que sql nos puede dar el mínimo de un grupo dado pero no los campos que lo acompañan...(MsAccess (no se si MsSQLserver) implementa FIRST() y LAST() que podían haber servido pero no es SQL estándar).

Fijate que la cardinalidad de mis subconsultas tiene como máximo n registros y sin repeticiones.


FINALMENTE Y EN MAYÚSCULAS ESTA NO ES LA ÚNICA SOLUCIÓN Y NO SE SI DE TODAS LAS POSIBLES ES LA MAS EFICIENTE
__________________
Quim
--------------------------------------------------
Ayudar a ayudar es una buena práctica!!! Y da buenos resultados.

Última edición por quimfv; 19/01/2011 a las 04:53