WHERE子句或ON子句中的INNER JOIN条件?

时间:2014-01-17 21:27:43

标签: mysql sql performance inner-join

我今天错误地输入了一个查询,但它仍然有效,并给出了预期的结果。我打算运行这个查询:

SELECT e.id FROM employees e JOIN users u ON u.email=e.email WHERE u.id='139840'

但我不小心跑了这个查询

SELECT e.id FROM employees e JOIN users u ON u.email=e.email AND u.id='139840'

(请注意最后一句中的AND而不是WHERE

并且都从用户ID返回了正确的员工ID。

这两个查询之间有什么区别?第二种形式是否只加入满足条件的2个表的成员,而第一个表是否会加入整个表,然后运行查询?一个比另一个更有效还是更低效?这是我缺少的其他东西吗?

谢谢!

5 个答案:

答案 0 :(得分:6)

对于这样的内连接,它们在逻辑上是等价的。但是,您可以运行到join子句中的条件意味着与where子句中的条件不同的情况。

作为一个简单的例子,假设您像这样进行左连接;

select x.id
from x
       left join y
         on x.id = y.id
;

这里我们从x中获取所有行,无论y中是否存在匹配的id。现在让我们假设我们的连接条件增长 - 我们不只是根据id而是在id_type上查找y中的匹配。

select x.id
from x
       left join y
         on x.id = y.id
         and y.id_type = 'some type'
;

再次,这给出了x中的所有行,无论y中是否存在匹配(id,id_type)。

但这是非常不同的:

select x.id
from x
       left join y
         on x.id = y.id
where y.id_type = 'some type'
;

在这种情况下,我们选择x的所有行并尝试匹配y中的行。现在对于y中没有匹配的行,y.id_type将为null。因此,不满足y.id_type ='some type',因此丢弃那些没有匹配的行,这实际上将其转换为内连接。

长话短说:对于内连接而言,条件在哪里并不重要,但对于外连接它可以。

答案 1 :(得分:4)

优化器会对它们进行相同的处理。你可以用EXPLAIN来证明这一点。

因此,写一个更清晰的。

SELECT e.id
FROM employees e JOIN users u ON u.email=e.email
WHERE u.id='139840'

答案 2 :(得分:3)

在INNER JOIN的情况下,两个查询在语义上是相同的,这意味着它们保证具有相同的结果。如果您使用的是OUTER连接,则两个查询的含义可能会有很大不同,结果会有所不同。

在性能方面,我希望期望这两个查询会产生相同的执行计划。但是,查询引擎可能会让您大吃一惊。唯一知道的方法是查看两个查询的执行计划。

答案 3 :(得分:2)

如果它是外连接而不是内连接,则会得到意想不到的结果,但是当使用内连接时,无论使用其他连接条件而不是WHERE子句,都没有什么区别。

在性能方面,他们很可能是相同的,但不能确定。

答案 4 :(得分:1)

我把我的同事们带到我们的团队工作中。这个响应有点以SQL Server为中心而不是MySQL。但是,优化器在SQL和MySQL之间的操作应该有相似之处。

一些想法: 基本上,如果你必须添加一个WHERE,还需要进行额外的表扫描以验证每个条件的相等性(使用AND或数据集进行数量级的增加,OR,在第一个真实条件下进行决策) - 如果你给出的例子中有一个id指针,那么它反而非常快,如果你必须找到属于公司或部门的所有记录,它就会变得更加模糊,因为你可能有多个记录。如果可以应用equals条件,则在使用具有数十亿行的AuditLog或EventLog表时,它会更有效。人们不会真正看到这对小桌子(大约200,000行左右)的巨大好处。

来自:Allesandro Alpi http://suxstellino.wordpress.com/2013/01/07/sql-server-logical-query-processing-summary/

来自:Itzik Ben-Gan http://tsql.solidq.com/books/insidetsql2008/Logical%20Query%20Processing%20Poster.pdf