MySQL Left Join Subquery with *

Posted

技术标签:

【中文标题】MySQL Left Join Subquery with *【英文标题】: 【发布时间】:2013-11-02 10:53:39 【问题描述】:

我正在将一个相当简单的查询与 JOIN 语句中的子查询组合在一起。仅当我在子查询选择中包含 * 时才有效。为什么?

这行得通

$sql = 'SELECT locations.id, title, name, hours.lobby
        FROM locations
        LEFT JOIN states ON states.id = locations.state_id
        LEFT JOIN (SELECT *, type_id IS NOT NULL AS lobby FROM location_hours) AS hours ON locations.id = hours.location_id
        GROUP BY locations.id';

这不是

$sql = 'SELECT locations.id, title, name, hours.lobby
        FROM locations
        LEFT JOIN states ON states.id = locations.state_id
        LEFT JOIN (SELECT type_id IS NOT NULL AS lobby FROM location_hours) AS hours ON locations.id = hours.location_id
        GROUP BY locations.id';

我应该这样做吗?如果您不需要所有字段,我认为 * 不是最好的?

【问题讨论】:

【参考方案1】:

试试这个(如果我正确理解你的意图,你想过滤 type_id 不为空):

   SELECT locations.id, title, name, hours.lobby
     FROM locations
LEFT JOIN states
       ON states.id = locations.state_id
LEFT JOIN (SELECT location_id, type_id AS lobby
             FROM location_hours 
            WHERE type_id IS NOT NULL) AS hours
       ON locations.id = hours.location_id
 GROUP BY locations.id';

解释是您必须在内部查询中选择外部查询中引用的所有字段。

【讨论】:

您从子查询中仅选择一个字段时的问题是您无法执行 join 语句,因为如果您仅选择 type_id,子查询不会提供 hours.location_id。 这是有道理的。我想很明显。无论如何,这行得通。谢谢。 还要检查你是否真的需要使用(在第二种情况下)LEFT JOIN 而不是 JOIN。如果您不想要 NULL type_id 那么我假设您实际上可能想要运行 JOIN (通常更快)。【参考方案2】:

由于您希望 type_id 具有非 NULL 值,因此您根本不应该使用 LEFT JOIN。您将需要以下内容,它使用标准 JOIN。

$sql = 'SELECT locations.id, title, name, location_hours.type_id
        FROM locations
        JOIN location_hours ON location_hours.location_id = locations.id
        LEFT JOIN states ON states.id = locations.state_id
        WHERE location_hours.type_id IS NOT NULL
        GROUP BY locations.id';

JOIN 的全部意义在于它只连接实际存在的行。因此,您不会得到任何 location_hours 没有与 location.id 对应的 location_id 的行。然后,您只需过滤掉 location_hours.type_id 的 NULL 值。

【讨论】:

如果我只运行一个连接它的位置行。我想要所有位置行。然后我想看看是否为这些位置设置了小时数,看看是否有 NULL 值。 我不确定我是否明白你的意思。你能改写一下吗?顺便说一句,您的 LEFT JOIN 不起作用的原因是因为子查询没有选择 location_id 但您将它用于 ON 条件。 如果我运行 JOIN,它会排除不存在小时 type_id 的行。我想获取所有位置行,然后查看每个位置的 type_id 是否有值。我正在使用该值来确定是否需要为该特定位置添加或编辑小时数。 我想你可能不明白 JOIN 是如何工作的。这是我用简单的英语写的查询所做的。首先,它从 locations 表中检索所有行。然后,对于它检索到的每个 id 值,它会查看 location_hours 表并获取所有 location_id 等于该 location_id 的行i>身份证。因此,如果有 10 行 location_id = 1,那么新结果集将有 10 行 locations.id = 1 和 location_hours.location_id = 1。然后它过滤检查 type_id 不为空。

以上是关于MySQL Left Join Subquery with *的主要内容,如果未能解决你的问题,请参考以下文章

LEFT JOIN 和 SUBQUERY 与空列 / null 作为结果

Mysql join with subquery join 使用相关名称

将这些 DB2 SUBQUERY 重写为 Join

Hibernate Criteria:在 Subquery/DetachedCriteria 中执行 JOIN

MySQL JOIN Summary

MYSQL 优化