我今天错误地输入了一个查询,但它仍然有效,并给出了预期的结果。我打算运行这个查询:
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个表的成员,而第一个表是否会加入整个表,然后运行查询?一个比另一个更有效还是更低效?这是我缺少的其他东西吗?
谢谢!
答案 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