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
)。
我正在尝试加入两个 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
)。