我想知道为什么这个查询仍然可以完美运行。我认为 WHERE 子句总是必须以 WHERE
开头?
SELECT `persons`.*
FROM `persons`
LEFT JOIN `team_memberships`
ON (`team_memberships`.`participant` = `persons`.`id`)
JOIN `teams`
ON (`teams`.`id` = `team_memberships`.`team`)
JOIN `departments`
ON (`departments`.`id` = `teams`.`department`)
JOIN `areas`
ON (`areas`.`id` = `departments`.`area`)
JOIN `companies`
ON (`companies`.`id` = `areas`.`company`)
[NO WHERE HERE]
AND `persons`.`id` = ?
最佳答案
您刚刚在 AND
子句中添加了 ON
。 ON
子句只是计算一个 bool 值真或假,所以 AND
和例如 OR
bool 运算符是允许的,所有关于括号等的常用规则也适用。
将特定于特定连接表的条件从 WHERE
子句移动到适当的 ON
子句中通常是有利的 - 如果没有其他原因,只是为了提高可读性。
在继续连接其他表之前限制连接的结果是合乎逻辑的*,而不是返回一个大的结果集,然后在最后用 WHERE
子句过滤它。我说 *logical 是因为 DBMS 通常会优化您的查询,因此无论如何都会发生这种情况……但并非总是如此……有时可以通过在连接处进行过滤来改善性能不佳的查询(有时反之亦然)。
例如,如果你知道你只对 25 岁以上的人感兴趣,那么 JOIN persons ON persons.id = team_memberships.participant AND persons.age > 25
是有意义的,而不是包含随后只与年轻朋克相关的表的所有结果,只在最后过滤这些结果再次使用您的 WHERE persons.age > 25
子句。
我的理解是,在附加表达式的情况下,由于 ON
子句中的附加表达式,连接性能可能会降低:
age > 25
示例可能属于此类别),或 因此,例如,即使它使特定的连接变慢,从连接的结果集中剥离年轻的朋克仍然可能被证明是值得的,因为此时较小的结果集可能会使后续连接的性能大幅提高。但是,如果将它们包含在连接中只会使记录数量略有增加,那么在连接中包含它们然后在
WHERE
子句中将它们过滤掉实际上可能会更快。但我欢迎评论澄清/纠正我的理解。
编辑:根据下面的@ITroubs 评论,我真的应该澄清一下,如果连接是
INNER JOIN
,那么无论附加过滤条件是否在 ON
或 WHERE
子句中,最终结果集都将相同,但例如在 OP 的原始语句中例如,如果过滤条件从 LEFT JOIN ON team_memberships
移动到 WHERE
, LEFT JOIN ... ON ...
将产生完全不同的结果集。关于php - 特殊行为 : AND without WHERE still works,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15526985/