我想知道为什么这个查询仍能完美运行。我认为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` = ?
答案 0 :(得分:6)
您刚刚在AND
条款中添加了ON
。 ON
子句只是求值为布尔值true或false,因此允许使用AND
和OR
布尔运算符,并且所有关于括号等的通常规则也适用。
将WHERE
子句中特定于特定连接表的条件移动到适当的ON
子句中通常是有利的 - 如果除了提高可读性之外没有其他原因。
在继续加入其他表之前限制连接的结果是有意义的,而不是返回一个大的结果集,然后在最后使用{{ 1}}子句。我说*逻辑是因为DBMS通常会优化你的查询,所以无论如何都会发生这种情况......但并非总是如此......有时执行效果不佳的查询可以通过在连接处进行过滤来改进(有时候情况也相反)。
例如,如果您知道自己只对25岁以上的人感兴趣,则对WHERE
有意义,而不是包含所有后续表格的结果仅适用于年轻的朋克,只能在最后使用JOIN persons ON persons.id = team_memberships.participant AND persons.age > 25
子句过滤这些结果。
我的理解是,由于WHERE persons.age > 25
子句中的附加表达式(在附加表达式的实例中),连接性能可能会降低:
导致对联接中的每一行进行评估(因此上面的ON
示例可能属于此类别)或
依赖于一个/两个连接表中的非索引列,否则连接只依赖于索引列。
因此,例如,即使它使特定连接速度变慢,也可能仍然值得从连接的结果集中剥离年轻的朋克,因为此时较小的结果集可能会使后续连接的性能大幅提升。但是如果它们包含在连接中只会略微增加记录数量,那么实际上可以更快地将它们包含在连接中,然后在age > 25
子句中将它们过滤掉。
但我欢迎澄清/纠正我的理解的评论。
编辑:根据下面的@ITroubs评论,我真的应该澄清,如果连接是WHERE
,那么无论{{1}中是否有额外的过滤条件,最终结果集都是相同的}或INNER JOIN
子句,但是对于例如在OP的原始示例中,如果过滤条件从ON
移动到WHERE
,LEFT JOIN ON team_memberships
将产生完全不同的结果集。 / p>
答案 1 :(得分:2)
如果我没有弄错,那么mysql执行你的查询如下:
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`) AND `persons`.`id` = ?')
答案 2 :(得分:0)
Last AND不是WHERE子句的一部分,它是JOIN子句
的一部分答案 3 :(得分:0)
它有效,因为您实际上没有WHERE
子句,您的条件AND persons.id = ?
是最后JOIN
答案 4 :(得分:0)
它实际上意味着
join `companies` on ON (`companies`.`id` = `areas`.`company`) AND persons.id = ?
所以,既然你正在进行内连接 - 它几乎是*等价的。一旦你切换到计算机连接或复杂查询 - 某些东西就会破裂。
答案 5 :(得分:0)
它有效,请参阅http://dev.mysql.com/doc/refman/5.0/en/join.html,但请注意它们如何使用括号。