使用JOIN时WHERE子句vs ON

假设我有以下T-SQL代码:

从Foo f中选择*
b.BarId=f.BarId上的内连接杆b;
其中,b.被批准=1;

以下命令还返回相同的行集:

从Foo f中选择*
(b.IsApproved=1)和(b.BarId=f.BarId)上的内部连接杆b;

这可能不是这里的最佳示例,但这两者之间有性能差异吗

只是要注意与外部联接的区别。一个查询,其中b.IsApproved(在右侧表格的条形图上)的过滤器被添加到连接的on条件中:

选择*
来自富福
左外连接杆b打开(b.IsApproved=1)和(b.BarId=f.BarId);

与在WHERE子句中放置过滤器是否相同:

选择*
来自富福
左侧外部连接杆b打开(b.BarId=f.BarId)
式中(b.i批准=1);

由于对于Bar的“失败”外部联接(即,对于f.BarId没有b.BarId),这将使所有此类失败联接行的b.IsApproved保持为NULL,然后将过滤掉这些行

另一种方法是,对于第一个查询,LEFT-OUTER-JOIN Bar b ON(b.IsApproved=1)和(b.BarId=f.BarId)将始终返回左表行,因为LEFT-OUTER-JOIN保证即使连接失败也会返回左表行。但是,当(b.IsApproved=1)为false时,将(b.IsApproved=1)添加到左外部联接on条件的效果是将任何右表列清空,即按照通常应用于(b.BarId=f.BarId)上的左联接条件的相同规则

更新
为了完成Conrad提出的问题,可选过滤器的等效LOJ为:

选择*
来自富福
左侧外部连接杆b打开(b.BarId=f.BarId)
其中(b.IsApproved为空或b.IsApproved=1);

即< 子句需要考虑连接是否失败>代码>(NULL)和忽略过滤器的情况,以及连接成功的地方和必须应用的筛选器。(b.IsApprovedb.BarId可以测试NULL

我在这里放了一个SqlFiddle,它演示了b的不同位置之间的差异。IsApproved过滤器相对于连接

发表评论