在WHERE子句中筛选和在ON子句中筛选有什么区别?

4

我想知道使用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;

第二个查询:
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

两个查询的结果:

result


1
在这种情况下,两者的结果都相同,因为您正在比较来自2个表的数据。第一个将仅选择符合绑定条件的数据,而第二个将绑定这两个表并过滤掉条件。 - Nadeem_MK
1
在SSMS工具栏上寻找一个带有“包括实际执行计划”工具提示的按钮 - 单击它,然后运行两个查询并进行比较。 - Mathieu Guindon
3个回答

6

我的回答可能有些离题,但我想强调一个可能在将INNER JOIN转换为OUTER JOIN时会出现的问题。

在这种情况下,在ON或WHERE子句中使用谓词(测试条件)最重要的区别是,如果您将要留出的表的字段放在WHERE子句中,则可能会 无意中将LEFT或RIGHT OUTER JOINS转换为INNER JOINS

例如,在表A和B之间进行LEFT JOIN,如果您在WHERE子句中包含涉及B字段的条件,则结果集中很可能不会返回来自B的空行。 实际上,并且隐含地将LEFT JOIN转换为INNER JOIN。

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

例如,请看下面的查询:

SELECT * FROM A 
LEFT JOIN B
   ON A.ID=B.ID

查询还会返回A表中与B表不匹配的行。
接下来看这个第二个查询:
SELECT * FROM A 
LEFT JOIN B
WHERE A.ID=B.ID

这个第二个查询不会返回任何来自A表的行,如果你指定了LEFT JOIN的话,即使你认为它会返回。这是因为测试A.ID=B.ID将在结果集中省略任何B.ID为空的行。

这就是为什么我更喜欢把谓词放在ON子句中而不是WHERE子句中的原因。


我在这里学到的重要一点是,在where子句之前,ON子句会被执行,这就是为什么结果在连接之后被过滤的原因。感谢您的回答! - daniel_aren

5

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

与从表中请求数据然后过滤不同,使用on子句可以首先过滤第一个数据集,然后将数据连接到其他表。因此,匹配的数据更少,结果更快。


3

以上两个查询的输出结果没有区别,它们都得到相同的结果

当您使用On子句时,联接操作仅联接满足On子句中条件的行。

而在Where子句中,联接操作会联接所有行,然后根据指定的where条件进行过滤。

因此,显然On子句更有效,应优先使用On子句而非where条件


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接