JOIN 子句中的条件是邪恶的 SQL

Posted

技术标签:

【中文标题】JOIN 子句中的条件是邪恶的 SQL【英文标题】:Is condition in the JOIN clause evil SQL 【发布时间】:2013-04-29 04:56:19 【问题描述】:

在 JOIN 子句或 WHERE 子句中添加 SQL 条件更好吗? SQL 引擎是否针对这两种方式进行了优化?这取决于引擎吗?

是否总是可以用 WHERE 子句中的条件替换 JOIN 子句中的条件?

这里的例子来说明我对条件的意思

SELECT      role_.name
FROM        user_role
INNER JOIN  user ON user_role.user_id_ = user.id AND
                    user_role.user_id_ = @user_id
INNER JOIN  role ON user_role.role_id = role_.id

对比

SELECT      role_.name
FROM        user_role
INNER JOIN  user ON user_role.user_id_ = user.id
INNER JOIN  role ON user_role.role_id = role_.id
WHERE       user.id = @user_id

【问题讨论】:

【参考方案1】:

如果使用 INNER JOIN,JOIN 子句和 WHERE 条件中的 SQL 条件是等价的。

否则,如果使用任何其他 JOIN(如 LEFT/RIGHT)而不是在基于条件匹配行之后,则会发生另一个步骤,即添加 OUTER ROWS ,即不匹配的行。

WHERE 条件只是过滤掉所有不匹配的行。

See this thread

【讨论】:

假设 op 没有消除 where 子句中的 NULL,那么您对左/右的判断是正确的,这是一个很好的假设,但我喜欢陈述假设。另请注意,mysql 不支持 FULL OUTER JOINS 但 sql-server (op 选择了两个标签) 支持。 这正是我在 google 上搜索的内容,在 JOIN 和 WHERE 中如何处理 NULL 值..感谢您的输入..【参考方案2】:

在 join 子句中包含非键条件不仅可以,尤其是在此查询中更可取,因为您可以避免与其他表的某些连接,这些连接进一步连接到 on 子句所属的表。

Where 子句在所有连接都完成后进行评估 - 它是结果集的过滤器。但是通过将条件放在 join 子句中,您可以在它们被 bing 连接时停止被连接的行。

在你的情况下没有区别,因为你没有任何下表,但我经常使用他的技术来提高我的查询性能。

【讨论】:

【参考方案3】:

通过查看为这两个查询生成的计划,我们可以看到在 INNER JOIN 或 WHERE 子句中包含条件会生成相同的计划。

但是在 WHERE 子句中使用条件的问题是您将无法处理 OUTER JOINs

【讨论】:

以上是关于JOIN 子句中的条件是邪恶的 SQL的主要内容,如果未能解决你的问题,请参考以下文章

SQL左连接与JOIN条件中的过滤器与WHERE子句中的过滤器[重复]

Spark SQL 中的 where 子句与 join 子句

Sql_join left right

LINQ Join 与 On 子句中的多个条件

为啥以及何时在 WHERE 子句中带有条件的 LEFT JOIN 不等于在 ON 中的相同 LEFT JOIN? [复制]

join 子句中的表达式之一的类型不正确。对“加入”的调用中的类型推断失败。-具有多个条件的 Linq JOIN