Sql 外部联接中的条件给出与WHERE条件不同的结果

Sql 外部联接中的条件给出与WHERE条件不同的结果,sql,postgresql,Sql,Postgresql,在尝试外部联接查询时,我注意到将一个条件从where子句更改为join子句会更改结果。这让我很惊讶,但我简化了表格和查询,如下所示,现在我想我明白了,但我希望听到一个可靠的解释 create table t0 (id int, b int); create table t1 (id int, b int); insert into t0 (id, b) values (1, 10), (2, 10); insert into t1 (id, b) values (1, 2); select t

在尝试
外部联接
查询时,我注意到将一个条件从
where
子句更改为
join
子句会更改结果。这让我很惊讶,但我简化了表格和查询,如下所示,现在我想我明白了,但我希望听到一个可靠的解释

create table t0 (id int, b int);
create table t1 (id int, b int);
insert into t0 (id, b) values (1, 10), (2, 10);
insert into t1 (id, b) values (1, 2);

select t0.id, t0.b
from t0
left outer join t1 on 
    t0.id = t1.id
where
    t0.b = 10
    and
    t1.b = 2
;
 id | b  
----+----
  1 | 10
(1 row)
现在,我将其中一个条件从
where
移动到
join
子句:

select t0.id, t0.b
from t0
left outer join t1 on 
    t0.id = t1.id
    and
    t1.b = 2
where 
    t0.b = 10
;
 id | b  
----+----
  1 | 10
  2 | 10
(2 rows)

您知道如何编写直接的推理吗?

外部联接的
on
条件只确定联接是否成功。如果联接失败,则联接列将填充
null

另一方面,
where
子句从结果集中过滤出整行

为了更清楚地说明这一点,将d
t1.b
添加到结果集中。使用
t1.b=2
作为
where
条件,可以得到:

t0.id   t0.b   t1.id   t1.b
1       10     1       2
相对于
t1.b=2
作为
on
条件:

t0.id   t0.b   t1.id   t1.b
1       10     1       2
2       10     NULL    NULL

您可以看到为什么
where
子句将第二行过滤掉:
null=2
不是真的。

外部联接的
on
条件仅确定联接是否成功。如果联接失败,则联接列将填充
null

另一方面,
where
子句从结果集中过滤出整行

为了更清楚地说明这一点,将d
t1.b
添加到结果集中。使用
t1.b=2
作为
where
条件,可以得到:

t0.id   t0.b   t1.id   t1.b
1       10     1       2
相对于
t1.b=2
作为
on
条件:

t0.id   t0.b   t1.id   t1.b
1       10     1       2
2       10     NULL    NULL

您可以看到为什么
where
子句将第二行过滤掉:
null=2
不是真的。

或者换一种方式:外部联接表上的
where
条件将外部联接转换为内部联接。或者换一种方式:外部联接表上的
where
条件将外部联接转换为内部联接参加