T-SQL:连接上的附加谓词与WHERE子句

T-SQL:连接上的附加谓词与WHERE子句,sql,tsql,Sql,Tsql,在JOIN语句中添加附加谓词与将它们作为附加子句添加到WHERE语句中有什么区别吗 示例1:WHERE子句上的谓词 select emp.* from Employee emp left join Order o on emp.Id = o.EmployeeId where o.Cancelled = 0 select emp.* from Employee emp left join Order o on emp.Id = o.EmployeeId and o.Cancelled = 0

在JOIN语句中添加附加谓词与将它们作为附加子句添加到WHERE语句中有什么区别吗

示例1:WHERE子句上的谓词

select emp.*
from Employee emp
left join Order o on emp.Id = o.EmployeeId
where o.Cancelled = 0
select emp.*
from Employee emp
left join Order o on emp.Id = o.EmployeeId and o.Cancelled = 0
示例2:JOIN语句上的谓词

select emp.*
from Employee emp
left join Order o on emp.Id = o.EmployeeId
where o.Cancelled = 0
select emp.*
from Employee emp
left join Order o on emp.Id = o.EmployeeId and o.Cancelled = 0

我已经从我的一些同事那里得到了答案,但如果他们不在这里发布,我会自己添加一个答案

这两个示例都假设谓词将“right”表上的列与标量值进行比较

性能
如果谓词位于
连接上
,那么“right”表将被预先过滤。如果谓词是
WHERE
子句的一部分,则返回所有结果,并在返回结果集之前在末尾过滤一次

返回的数据

如果谓词是
WHERE
子句的一部分,那么在“right”值为null(即没有连接行)的情况下,整个行将不会在最终结果集中返回,因为谓词会将值与
null
进行比较,因此返回false。

对于第一条语句,由于WHERE条件,外部联接将有效地转换为内部联接,因为它将过滤掉employee表中未找到订单的所有行(因为o.Cancelled将为null)


因此,这两个语句的作用不同。

为了解决附加谓词位于左表中的一列上的情况,这仍然会产生差异,如下所示

WITH T1(N) AS
(
SELECT 1 UNION ALL
SELECT 2
), T2(N) AS
(
SELECT 1 UNION ALL
SELECT 2
)
SELECT T1.N, T2.N, 'ON' AS Clause
FROM T1 
LEFT JOIN T2 ON T1.N = T2.N AND T1.N=1
UNION ALL
SELECT T1.N, T2.N, 'WHERE' AS Clause
FROM T1 
LEFT JOIN T2 ON T1.N = T2.N 
WHERE T1.N=1
返回

N           N           Clause
----------- ----------- ------
1           1           ON
2           NULL        ON
1           1           WHERE
下面是另一个例子(四个案例)

结果:

first Query       1      A      1      A
first Query       2      B      NULL   NULL
second Query      1      A      1      A
Third Query       1      A      1      A
Third Query       2      B      NULL   NULL
Fourth Query      1      A      1      A
Fourth Query      1      A      1      A

正确可以返回不同的结果,但我认为它确实需要一些示例数据来显示这一点。是的,我试图避免使用“正确”或“不正确”这两个词,因为它们确实不同。可能只想返回满足谓词的对应“右”行的记录。如果只想返回对应“右”行的记录,则应使用联接(或使用完整语法的内部联接)。使用左联接会向读取查询的人发送冲突消息,但不清楚该查询应该执行什么操作。如果左联接的谓词不匹配,它会给出一个空值行,但
将过滤其中的
,并且不显示该行。你主要有数差。完全不同而且容易出错