Domanda

Questo è molto simile a Limitare i risultati dalla tabella unita a una riga, ma sto lottando per farlo funzionare esattamente come ho bisogno ...

La struttura della tabella è molto simile:

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)
);

Popola i tavoli 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);

Voglio fare una selezione che restituisce tutti e 3 i prodotti, con immagini appropriate. Simile a:

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

Una soluzione semplice sarebbe:

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

Ma questo fallisce se voglio aggiungere e restituire un altro campo da TBLProductImages (AltText per esempio)

Ho impostato un violino a http://sqlfiddle.com/#!2/883c5/1

Grazie

È stato utile?

Soluzione

Questo funzionerà, ma è piuttosto brutto

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

Altri suggerimenti

È necessario utilizzare l'aggregazione (in particolare GROUP BY). Tu vuoi GROUP BY il nome del prodotto e utilizzare un file LEFT JOIN in modo che l'immagine non debba esistere.

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

Si noti che l'immagine selezionata in questo caso è a caso (Anche se di solito sarà dentro intImageID ordine). Ciò presuppone che l'immagine effettiva recuperata non sia importante fintanto che è associata al prodotto dato.

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

Per quell'output esatto, potrebbe essere necessario modificare l'istruzione insert per la tabella tblproductImages come:

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);

E utilizzare l'istruzione Select seguente:

SELECT tP.intProductID, tp.strProductName, tPI.strImageName
FROM tblProducts AS tP 
INNER JOIN tblProductImages AS tPI ON tP.intProductID = tPI.intProductID;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top