只要注意与外连接的区别。其中b.IsApproved
过滤器(上右表,酒吧)被添加到JOIN
的ON
条件查询:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
是不一样放置过滤器的WHERE
子句中:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
由于对“失败”外连接到Bar
(即在没有b.BarId
为f.BarId
),这将离开b.IsApproved
作为NULL
所有这样的发加入连接行,然后这些行将被过滤掉。
查看此问题的另一种方法是,对于第一个查询,LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
将始终返回LEFT表行,因为LEFT OUTER JOIN
保证即使连接失败,LEFT表行也会返回。但是,(b.IsApproved = 1)
条件的(b.IsApproved = 1)
的作用是当(b.IsApproved = 1)
为假时(即按照通常应用于(b.BarId = f.BarId)
上的LEFT JOIN
条件的相同规则)将任何右表列中的NULL排除。
更新: 要完成康拉德提出的问题,一个可选的过滤器相当于LOJ是:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
即WHERE
条款需要考虑两个条件是否加入失败(NULL)
和过滤器将被忽略,并且连接成功并且必须应用过滤器。(b.IsApproved
或b.BarId
可以为NULL
被测试)
我已经把一个SqlFiddle together here这表明相对于JOIN
的b.IsApproved
滤波器的各种放置之间的差异。
这里有一个类似的问题:http://stackoverflow.com/questions/2509987/which-sql-query-is-faster-filter-on-join-criteria-or-where-clause – 2012-04-24 11:52:59
机器会计算出来并对其进行适当优化。但是,对于需要调试\修改\支持代码的人来说,在“WHERE”中保留过滤条件并在“ON”中加入条件。 – 2012-04-24 11:58:42
@KM。我并不总是知道如何区分什么是连接条件和什么是过滤器。例如[在这个答案](http://stackoverflow.com/a/9303069/119477)我认为它更好的加入,所以是“加入条件”呢? [这是另一个例子](http://stackoverflow.com/a/6473403/119477),我甚至不知道如何重写等价的where子句。 – 2012-04-24 17:55:31