Php MySQL连接:如果满足条件,则从子表中选择一行,否则为空

Php MySQL连接:如果满足条件,则从子表中选择一行,否则为空,php,mysql,join,left-join,Php,Mysql,Join,Left Join,我想把两张桌子合在一起,但遇到了一些麻烦。 这是主表,packs 这是第二张表,media 媒体用于存储包的图像。每个包可以有0个或多个图像。当包中有图像时,其中一个将把is_default字段设置为1,以指示要显示的主图像 我想得到所有的包和一个图像为每个。如果没有图像,则只需一个简单的NULL,否则得到的图像为默认值 这是我的问题 SELECT pack.*, ( SELECT media.src FROM packs pack LEFT JOIN packs_medi

我想把两张桌子合在一起,但遇到了一些麻烦。 这是主表,
packs

这是第二张表,
media

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

我想得到所有的包和一个图像为每个。如果没有图像,则只需一个简单的
NULL
,否则得到的图像
为默认值

这是我的问题

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
我一共有三个包,其中只有一个有一些图片。 查询返回3个结果。问题是这三个结果都具有相同的
图像
,而只有一个结果应该具有
图像
字段null/空

有没有办法只用一个查询就可以做到这一点?我希望避免在循环中查询
媒体


谢谢

您需要的是相关子查询,而不是联接:

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
。因此,也不需要
分组依据

注意对
ORDER BY
子句的更改。这将确保首先选择默认值


并且,您的查询为所有行获取相同的值,因为子查询独立于外部查询。所以,总是选择相同的值。

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

但是,如果您像我一样将此条件添加到
左连接
部分,它就像一个符咒。这是因为,根据
左连接的定义,如果
左连接
条件满足,则返回图像;如果不满足,则返回
NULL

因此,结果应该是:

SELECT pack.*, media.src
FROM packs pack 
LEFT JOIN media
ON media.pack_id = pack.id
AND media.is_default = 1
我认为你不应该加入群体,它只是把事情搞砸了

如果您想在没有
的情况下解决您的问题,则默认为
。。。好吧,这是一个更难破解的问题,但我想我有一个解决方案,它不会停留在长长的条件行和子查询中。遗憾的是,我觉得这个问题没有子查询是无法解决的。我的想法不是选择其
媒体默认值等于
1
的项目,而是选择媒体默认值最高的项目。详情如下:

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
降序排列所有的数据,然后返回到外部查询,只使用当前的
包id
(我希望它是这样工作的)。如果有1,它显然将是第一项,否则它将是随机项,最有可能的是ID的第一个顺序。你只需要取那个元素并使用它。我不能保证它是否有效。尝试在
中使用
,而不是
=
作为可能的错误修复


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

m.is_default=1按m.is_default
?谢谢。它确实有效。只是一个简单的问题。如果有图像但没有一个具有is_default=1,是否仍然可以获得一个?现在,如果一个包有图像但没有默认值,它将返回null。@C.Ovidiu-删除子查询中的
和m.is_default=1
条件,非常感谢您。它工作得很好,看起来很干净。您是否介意告诉我,如果is_默认字段不是1,但包中仍有图像,是否可以选择第一个图像?如果是1,则获取该图像。否则,获取第一个或仅另一个图像,以便该包至少有一个图像。如果包中没有,则为空。我将答案更改为回复您的评论。我希望这能有所帮助,但我确实在努力推动改变代码的另一部分,使这一部分更容易。相信我,你最好想要两个你能理解的小问题,而不是一周后你甚至都记不起来的一个长问题。