探索 JOIN 中 WHERE 子句和 ON 条件的区别
SQL 实践者在执行 JOIN 操作时经常交替使用 WHERE 子句和 ON 条件。虽然两种方法可以返回相同的结果,但需要考虑一些细微差别。
在提供的示例中,提供了两个 SQL 查询:
SELECT * FROM Foo AS f INNER JOIN Bar AS b ON b.BarId = f.BarId WHERE b.IsApproved = 1;
和
SELECT * FROM Foo AS f INNER JOIN Bar AS b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
两个查询返回相同的行集,但它们的执行有一个关键的区别。当过滤器放置在 WHERE 子句中时,它会在 JOIN 操作之后应用。这意味着 JOIN 将从两个表中检索所有匹配的行,即使是 b.IsApproved 为 false 的行。然后,WHERE 子句会过滤掉不满足条件 b.IsApproved = 1 的行。
相反,当过滤器置于 ON 条件中时,会在 JOIN 之前评估条件。因此,只有 b.BarId 和 b.IsApproved 都满足指定条件的行才会包含在 JOIN 中。
外部联接和过滤器放置
但是,在处理外连接时,这种差异变得尤为重要。考虑以下左外连接查询:
SELECT * FROM Foo AS f LEFT OUTER JOIN Bar AS b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
在这种情况下,ON 条件下的过滤器将排除 b.IsApproved 为 false 的行或给定 f 没有匹配的 b.BarId 的行.BarId。此行为与将过滤器放在 WHERE 子句中不同:
SELECT * FROM Foo AS f LEFT OUTER JOIN Bar AS b ON (b.BarId = f.BarId) WHERE b.IsApproved = 1;
在第二个查询中,b.IsApproved 为 false 或涉及失败联接的行仍将返回,但 b.IsApproved 将返回设置为 NULL。
因此,在使用外连接时,必须仔细考虑过滤器的放置。 ON 条件过滤连接之前的行,而 WHERE 子句过滤连接之后的结果。
为了完成讨论,如果您希望在左外连接中使用 OPTIONAL 过滤器,以下查询演示了正确的位置:
SELECT * FROM Foo AS f LEFT OUTER JOIN Bar AS b ON (b.BarId = f.BarId) WHERE b.IsApproved IS NULL OR b.IsApproved = 1;
此查询返回连接成功且 b.IsApproved 满足条件的行,以及连接失败的行(导致 NULL 值)对于 b.IsApproved)。
以上是SQL JOIN 中的 WHERE 与 ON:何时应该使用每个子句?的详细内容。更多信息请关注PHP中文网其他相关文章!