如果我运行以下SQL查询
SELECT *
FROM A
LEFT JOIN B
ON A.foo=B.foo
WHERE A.date = "Yesterday"
在WHERE
之前或之后评估JOIN
语句?
如果之后,编写此语句的更好方法是什么,只返回A
"Yesterday"
中的行加入B
?
答案 0 :(得分:9)
这取决于数据库。
在SQL Server上运行:SET SHOWPLAN_ALL ON
然后运行查询,您将了解运行时会发生什么。
答案 1 :(得分:7)
您对“评估”的想法并不正确,因为SQL是一种声明性语言。
BTW你可以看到查询执行计划。在MySQL中,使用关键字describe
为查询添加前缀,以查看执行计划。
答案 2 :(得分:6)
语义上:在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"
答案 3 :(得分:2)
确定满足查询的操作顺序是为什么特定数据库的查询优化器突发奇想。查询优化器尝试根据它可以从查询中收集的内容以及它手头有关数据库的任何统计信息(可能包括表的基数和某些数据分布)来生成一个好的“查询计划”(操作集)。
在您的情况下,答案可能取决于您是否在A.date上有二级索引
查询优化是一个相当丰富的主题。您正在使用的任何数据库的文档都有很多可以说的。
答案 4 :(得分:1)
取决于索引和统计数据。
您应该显示查询的执行路径,以确定应该应用哪些优化(如果有)。
答案 5 :(得分:1)
:
作为一般经验法则,在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
答案 6 :(得分:0)
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