[英]SQL order of operations
如果我运行以下SQL查询
SELECT *
FROM A
LEFT JOIN B
ON A.foo=B.foo
WHERE A.date = "Yesterday"
是否在JOIN
之前或之后评估WHERE
语句?
如果之后,什么是更好的方式编写此语句,以便只返回"Yesterday"
A
行加入B
?
这取决于数据库。
在SQL Server上,运行: SET SHOWPLAN_ALL ON
然后运行查询,您将了解运行时会发生什么。
您对“评估”的想法并不正确,因为SQL是一种声明性语言。
顺便说一下,你可以看到查询执行计划。 在MySQL中,使用关键字describe
为您的查询添加前缀以查看执行计划。
语义上:在JOIN之后。 但在这种情况下,时序没有区别,因为它位于JOIN的左侧。
正如你已经拥有的那样,“只有”昨天“中的A行加入了B”。
优化器可以自由地重新组织其操作顺序,具体取决于关系代数中的等价。
这只返回A.date =“Yesterday”并加入B,它可以在foo上找到匹配:
SELECT * FROM A
LEFT JOIN B
ON A.foo=B.foo
WHERE A.date="Yesterday"
这将返回所有A而不管任何条件,并加入B,其中A.date =“Yesterday”并且它在foo上找到匹配:
SELECT * FROM A
LEFT JOIN B
ON A.foo=B.foo
AND A.date="Yesterday"
确定满足查询的操作顺序是为什么特定数据库的查询优化器突发奇想。 查询优化器尝试根据它可以从查询中收集的内容以及它手头有关数据库的任何统计信息(可能包括表的基数和某些数据分布)来生成一个好的“查询计划”(操作集)。 。
在您的情况下,答案可能取决于您是否在A.date上有二级索引
查询优化是一个相当丰富的主题 您正在使用的任何数据库的文档将有更多关于它的说明。
取决于索引和统计数据。
您应该显示查询的执行路径,以确定应该应用的优化位置(如果有)。
在SQL Server中:
作为一般经验法则,在WHERE子句之前评估JOIN子句。
如果在连接部分需要过滤器的复杂连接,我会将它们与我的连接一起编写
SELECT *
FROM A
LEFT JOIN B
ON A.Foo1 = B.Foo1
And A.Date = 'Yesterday'
OUTER JOIN C
ON B.Foo2 = C.Foo2
JOIN D
ON B.Foo3 = D.Foo3
SELECT *
FROM (SELECT * FROM A WHERE Date = 'Yesterday') A
LEFT JOIN B
ON A.Foo1 = B.Foo1
OUTER JOIN C
ON B.Foo2 = C.Foo2
JOIN D
ON B.Foo3 = D.Foo3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.