区别在于条件的逻辑评估位置,这反过来会影响结果集。
在您的示例中(重新格式化),您有:
示例 1
SELECT COUNT(*)
FROM A LEFT JOIN B ON a.id = b.id
WHERE a.status = 2 AND b.id is NULL
示例2
SELECT COUNT(*)
FROM A LEFT JOIN B ON a.id = b.id AND a.status = 2
WHERE b.id is NULL
在第一个案例中,使用LEFT JOIN生成结果集; 然后在WHERE子句中过滤两个条件。
在第二个案例中,使用LEFT JOIN与
a.status
的筛选条件形成,并且在某些情况下可能会改变LEFT JOIN的结果集。然后,再通过主要的WHERE子句过滤这个结果集。
示例2基本上等效于:
示例2A
SELECT COUNT(*)
FROM (SELECT * FROM A WHERE a.status = 2) AS A
LEFT JOIN B ON a.id = b.id
WHERE b.id is NULL
对于一些查询来说(但可能不是这个查询),差异很重要。
让我们尝试创建一些简单的样本数据:
Table A Table B
id status id
4 2 1
5 3
示例1将有一个中间结果集:
a.id a.status b.id
4 2 null
5 3 null
WHERE子句可以消除第二行。
示例2将有一个中间结果集:
a.id a.status b.id
4 2 null
在这个例子中,最终结果是相同的,我无法找到任何数据不会得出相同结果的情况。
如果移动的查询条件在外部连接表上,并且较为复杂超过简单的相等比较,那么你可能会看到影响。
FROM (SELECT * FROM A WHERE a.status = 2) AS A
这个变量的情况作为“that”(我们称其为Example 2A),那么我向你提出挑战,让你提供一个样本数据集,在Example 2和Example 2A之间有所区别。 - Jonathan Leffler示例1
等同于示例2A
。 - ypercubeᵀᴹa.status = 2
从左连接条件移动到子查询中,并使它相等。难道示例2的中间结果有两行,而示例2A只有一行吗?如果说什么的话,你的第二个例子(2A)和第一个例子是相等的吧? - dotjoe