WHERE子句中的过滤与ON子句之间的区别是什么?

dan*_*ren 4 sql t-sql sql-server-2012

我想知道在使用WHERE子句或在内连接的ON中使用匹配是否有任何区别.

在这种情况下的结果是相同的.

第一个查询:

with Catmin as 
(
    select categoryid, MIN(unitprice) as mn
    from production.Products
    group by categoryid
) 
select p.productname, mn
from Catmin 
inner join Production.Products p
on p.categoryid = Catmin.categoryid
and p.unitprice = Catmin.mn;
Run Code Online (Sandbox Code Playgroud)

第二个查询:

with Catmin as 
(
    select categoryid, MIN(unitprice) as mn
    from production.Products
    group by categoryid
) 
select p.productname, mn
from Catmin 
inner join Production.Products p
on p.categoryid = Catmin.categoryid
where p.unitprice = Catmin.mn;          // this is changed
Run Code Online (Sandbox Code Playgroud)

结果两个查询:

结果

Ric*_*rdo 6

我的回答可能有点偏离主题,但我想强调一下当你将INNER JOIN变成OUTER JOIN时可能出现的问题.

在这种情况下,将谓词(测试条件)置于ON或WHERE子句之间的最重要区别在于,如果将表中的字段放在其中,则可以将LEFT或RIGHT OUTER JOINS转换为INNER JOINS而不会注意到它 WHERE子句.

例如,在表A和B之间的LEFT JOIN中,如果在WHERE子句中包含涉及B字段的条件,则很可能在结果集中不会从B返回空行.有效地,隐含地,您将LEFT JOIN转换为INNER JOIN.

另一方面,如果在ON子句中包含相同的测试,则将继续返回空行.

例如,请执行以下查询:

SELECT * FROM A 
LEFT JOIN B
   ON A.ID=B.ID
Run Code Online (Sandbox Code Playgroud)

该查询还将返回A中与B中的任何一个都不匹配的行.

进行第二个查询:

SELECT * FROM A 
LEFT JOIN B
WHERE A.ID=B.ID
Run Code Online (Sandbox Code Playgroud)

第二个查询不会返回A中与B不匹配的任何行,即使您认为它会因为您指定了LEFT JOIN.这是因为测试A.ID = B.ID将从结果集中省略B.ID为null的任何行.

这就是为什么我倾向于将谓词放在ON子句而不是WHERE子句中.


小智 5

结果完全相同.由于查询性能的提高,建议使用"ON"子句.

不是从表中请求数据然后通过使用on子句进行过滤,而是首先过滤第一个数据集,然后将数据连接到其他表.因此,给出了较少的数据匹配和更快的结果.