MySQL JOINS:Select 来自子 table 的一行满足条件,否则为 NULL

MySQL JOINS: Select one row from child table is condition is met, otherwise NULL

我正在尝试加入两个 table,但我遇到了一些问题。 这是主要的table,packs

这是第二个 table, media

media用于存储packs的图像。每个包可以有 0 个或多个图像。当包中有图像时,其中之一的 is_default 字段将设置为 1 以指示要显示的主图像。

我想要所有的包和每包一张图片。如果没有图像,那么只是一个简单的 NULL,否则得到图像 is_default.

这是我的查询。

SELECT 
    pack.*,
    ( SELECT media.src FROM packs pack LEFT JOIN packs_media media ON pack.id = media.pack_id WHERE media.is_default = 1 GROUP BY media.id LIMIT 1 ) AS image 
FROM packs pack 
LEFT JOIN packs_media ON media.pack_id = pack.id 
GROUP BY pack.id 
ORDER BY pack.id DESC

我一共三包,只有一包有图片。 查询returns3个结果。问题是所有三个结果都具有相同的 image,而只有一个应该具有 image 字段 null/empty.

有什么办法只用一个查询就可以做到这一点吗?我想避免在循环中查询 media table。

谢谢

您需要相关子查询而不是连接:

SELECT p.*,
      (SELECT m.src
       FROM packs_media m
       WHERE p.id = media.p 
       ORDER BY m.is_default DESC, m.id
       LIMIT 1
      ) AS image 
FROM packs p 
ORDER BY p.id DESC;

其实从问题的描述来看,外层查询也不需要JOIN。所以也不需要GROUP BY

请注意 ORDER BY 子句的更改。这保证首先选择默认值。

并且,您的查询对所有行获取相同的值,因为子查询独立于外部查询。因此,始终选择相同的值。

我最近遇到了类似的问题,老实说,它有一个非常非常好的解决方案。乍一看,一个明显的尝试是添加 WHERE 条件 is_default = 1。但是,如果我们这样做,在没有图像的地方,条件将不会满足,这意味着它应该 return NULL,它只是跳过那一行。

但是,如果像我一样将此条件添加到 LEFT JOIN 部分,它的效果就像一个魅力。这是因为如果 LEFT JOIN 条件满足,它 return 就是图像,如果不满足,它 return 就是 NULL,根据 [=15= 的定义].

所以结果应该是:

SELECT pack.*, media.src
FROM packs pack 
LEFT JOIN media
ON media.pack_id = pack.id
AND media.is_default = 1

而且我认为您不应该添加 GROUP BY,它只会把事情搞砸。

如果你想在没有 is_default 的情况下解决你的问题......好吧,这是一个更难破解的问题,但我认为我有一个解决方案不会陷入长篇大论条件和子查询。可悲的是,我觉得如果没有子查询就无法解决这个问题。我的想法不是选择 media.is_default 等于 1 的项目,而是选择 media.is_default 最高的项目。如下:

SELECT pack.*, media.src
FROM packs pack 
LEFT JOIN media
ON media.pack_id = pack.id
AND media.id = 
   (SELECT m.id FROM media m
    WHERE m.pack_id = media.pack_id
    ORDER BY m.is_default DESC
    LIMIT 1
   )

说明:它是这样工作的:我们按 is_default 降序排列,然后返回到外部查询以仅使用当前的 pack_id(我希望它能这样工作方式。)如果有一个 1,它显然将是第一个项目,否则它将是一个随机项目,很可能是 ID 顺序的第一个。你只需获取该元素并使用它。我无法保证它是否有效。尝试使用 IN 而不是 = 作为可能的错误修复。

但是,我建议这个解决方案。我宁愿改变以前的逻辑来避免这个问题(例如,当用户将媒体添加到空包时,该图片上的is_default = 1)。