使用 GROUP BY 获取具有最高值的条目

Using GROUP BY to get the entry with the highest value

我需要为每个产品创建一个带有预览图像的产品列表。

我有一个非常简单的产品数据结构。一个 table 用于产品,一个 table 用于产品图像。一个产品可以有任意数量的图像。结构如下所示:

PRODUCT
id | name
1    Test Product A
2    Test Product B
3    Test Product C

PRODUCTIMAGE
id | productId | file             | priority
1    1           foo.jpg            0
2    1           bar.jpg            1
3    2           something.png      1
4    2           yada.png           0
5    1           yougettheidea.gif  2

非常简单。唯一值得一提的是 productimages 有一个“优先级”,即 TINYINT 来确定给定产品的图像显示顺序。思路是:优先级越高,该图片在详情页的商品图片列表中应该越早显示。但是对于我们即将创建的这个产品列表,我只需要每个产品一张预览图片。

正如最初所述,我的目标是获取所有产品的列表。那么让我们从简单的开始:

SELECT *
FROM product

现在我也想在产品页面显示一张预览图,所以需要一点加入:

SELECT `p`.*,
    `pi`.`file` `previewImage`
FROM `product` `p`
LEFT JOIN `productImage` `pi` ON (`pi`.`productId` = `p`.`id`)
GROUP BY `p`.`id`

到目前为止一切顺利,这为我提供了每个产品一张预览图像以显示在产品列表中。还差一步:我要每个产品优先级最高的预览图作为预览图。所以我尝试使用子查询以所需的优先顺序获取产品图片:

SELECT `p`.*,
    `pi`.`file` `previewImage`
FROM `product` `p`
LEFT JOIN (
    SELECT *
    FROM `productImage`
    ORDER BY `priority` DESC
) `pi` ON (`pi`.`productId` = `p`.`id`)
GROUP BY `p`.`id`

但出于某种原因,这并没有(可靠地)为我提供每个产品具有最高优先级的产品图像。这是为什么?我认为 GROUP BY 选择了错误的 productImage 条目来保留,但为什么呢?它不应该选择第一个吗,由于子查询应该是优先级最高的那个?

您的分组依据是部分分组依据。您按 product.id 分组,因此 MySQL 将按产品对结果进行分组,但在每个组中,可以自由 return 来自 productimage table 的任何行。要获得确定性结果,table 中的每一列都需要包含在聚合函数(MIN、MAX 等)中,但这不会为您提供具有最高优先级的图像。

也就是说,如果您只想要 productimage table 中的一列,您可以在 select:

中使用子查询
select product.*, (
    select file
    from productimage
    where productimage.productid = product.id
    order by priority desc
    limit 1 -- this is the important bit
) as productimage_file
from product