Pregunta

Esto es muy similar a Limite los resultados de la tabla unida a una fila, pero estoy luchando para que funcione exactamente como necesito ...

La estructura de la tabla es muy similar:

CREATE TABLE tblProducts (
    intProductID int(11) NULL AUTO_INCREMENT,
    strProductName varchar(255) NULL,
    PRIMARY KEY (intProductID)
);

CREATE TABLE tblProductImages (
    intImageID int(11) NULL AUTO_INCREMENT,
    intProductID int(11) NULL,
    strImageName varchar(255) NULL,
    intOrder int(11) NULL,
    PRIMARY KEY (intImageID)
);

Uplpe las tablas con:

INSERT INTO tblProducts (strProductName)
VALUES
('Product #1'), ('Product #2'), ('Product #3');

INSERT INTO tblProductImages (intProductID, strImageName, intOrder) 
VALUES
(1, 'image_for_1.jpg', 1), 
(2, '1st_image_for_2.jpg', 1), 
(2, '2nd_image_for_2.jpg', 2);

Quiero hacer una selección que devuelva los 3 productos, con imágenes apropiadas. Similar a:

intProductID, strProductName, strImageName
1, Product #1, image_for_1.jpg
2, Product #2, 1st_image_for_2.jpg
3, Product #3, NULL

Una solución simple sería:

SELECT intProductID, strProductName, 
 (SELECT strImageName
  FROM tblProductImages
  WHERE tblProductImages.intProductID = tblProducts.intProductID
  ORDER BY intOrder
  LIMIT 1)
FROM tblProducts

Pero esto falla si quiero agregar y devolver otro campo desde el TBLProductimages (AltText, por ejemplo)

He configurado un violín en http://sqlfiddle.com/#!2/883c5/1

Gracias

¿Fue útil?

Solución

Este funcionará, pero es bastante feo

select p.intProductId, p.strProductName, pi.strImageName 
from tblProducts p
inner join tblProductImages pi on pi.intProductID = p.intProductId
inner JOIN (select min(intOrder) minOrder, intProductID
           FROM tblProductImages
           GROUP BY intProductID) s
           on s.intProductID = p.intProductID and s.minOrder = pi.intOrder
union
select p.intProductId, p.strProductName, pi.strImageName
from tblProducts p
left join tblProductImages pi on pi.intProductID = p.intProductId
where pi.intProductID is null;

alternativa :

select p.intProductId, p.strProductName, pi.strImageName
from tblProducts p
left join tblProductImages pi on pi.intProductID = p.intProductId
where pi.intProductId is null or pi.IntOrder = (select min(intOrder)
                                                from tblProductImages
                                                where intProductId = pi.intProductId);

Sqlfiddle

Otros consejos

Necesita usar agregación (específicamente GROUP BY). Tú quieres GROUP BY el nombre del producto y usar un LEFT JOIN para que la imagen no necesita existir.

SELECT strProductName, strImageName
FROM tblProducts LEFT JOIN tblProductImages USING (intProductID)
GROUP BY strProductName

Tenga en cuenta que la imagen seleccionada en este caso es aleatorio (aunque generalmente estará en intImageID ordenar). Esto supone que la imagen real recuperada no es importante siempre que esté asociada con el producto dado.

http://sqlfiddle.com/#!2/1391e6/1

Para esa salida exacta, es posible que deba modificar su instrucción Insertar para la tabla TBLProductimages como:

INSERT INTO tblProductImages (intProductID, strImageName, intOrder) VALUES
    (1, 'image_for_1.jpg', 1), (2, '1st_image_for_2.jpg', 1), (3, '2nd_image_for_3.jpg', 2);

Y use la siguiente declaración de selección:

SELECT tP.intProductID, tp.strProductName, tPI.strImageName
FROM tblProducts AS tP 
INNER JOIN tblProductImages AS tPI ON tP.intProductID = tPI.intProductID;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top