【问题标题】:MySQL returning 1 image for each productMySQL 为每个产品返回 1 张图片
【发布时间】:2013-12-03 14:10:00
【问题描述】:

这与Limit results from joined table to one row 非常相似,但我正在努力让它完全按照我的需要工作......

表结构非常相似:

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

用以下内容填充表:

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

我想做一个返回所有 3 个产品的 SELECT,并带有适当的图像。类似于:

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

一个简单的解决方案是:

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

但如果我想从 tblProductImages(例如 AltText)添加和返回另一个字段,这将失败

我在http://sqlfiddle.com/#!2/883c5/1 设置了一个小提琴

谢谢

【问题讨论】:

  • 您确定插入 tblProductImages 的值吗?因为它们都有 1 作为 intProductId... 这看起来与想要的结果不一致。
  • 你需要使用LEFT JOIN而不是你正在做的时髦的SELECT
  • 很好看的 Raphaël - 它已修复。 nrathaus - LEFT JOIN 不起作用,因为它将返回产品 2 的 2 条记录(两个图像),而我只想要 1 条。

标签: mysql


【解决方案1】:

这个可以,但是很丑

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;

替代方案:

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

【讨论】:

  • 太棒了——感谢拉斐尔。你的替代方案对我有用!
【解决方案2】:

您需要使用聚合(特别是GROUP BY)。您想GROUP BY 产品名称并使用LEFT JOIN 以便图像不需要存在。

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

请注意,在这种情况下选择的图像是随机的(尽管通常它会以intImageID 的顺序排列)。这假定检索到的实际图像并不重要,只要它与给定产品相关联即可。

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

【讨论】:

  • 谢谢,但我试过了,但恐怕我确实需要能够设置返回图像的顺序。
  • @JezB 你到底是什么意思?每个产品图像的返回顺序还是它们在聚合中返回的顺序?
  • 但我无法设置图像的顺序 - 在这种情况下,我可能首先需要 2nd_image_for_2.jpg...
  • @JezB 你怎么知道什么时候选择什么图片?
【解决方案3】:

对于准确的输出,您可能需要将表 tblProductImages 的插入语句修改为:

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

并使用下面的 Select 语句:

SELECT tP.intProductID, tp.strProductName, tPI.strImageName
FROM tblProducts AS tP 
INNER JOIN tblProductImages AS tPI ON tP.intProductID = tPI.intProductID;

【讨论】:

  • 抱歉 - 我更改了 INSERT 来解决这个问题。但结果仍然返回产品 2 的 2 条记录(均为图像),而产品 3 则没有返回...
猜你喜欢
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 2021-09-06
  • 1970-01-01
  • 2019-12-25
  • 1970-01-01
  • 2015-03-16
相关资源
最近更新 更多