首页 > 解决方案 > 左连接中“where”null和“on”之间的区别

问题描述

有人可以向我解释为什么

select "talent".* from "talent" 
left join "push" on "push"."talentId" = "talent"."id" 
where ("push"."offerId" = '403' or "push"."offerId" is null)

产生的结果少于

select "talent".* from "talent" 
left join "push" on "push"."talentId" = "talent"."id" and "push"."offerId" in ('403') 

在我看来,它应该归结为相同的结果,但事实并非如此,而且我不确定我错过了什么。

第一个不包含push表中没有条目的行。

我希望他们被or "push"."offerId" is null.

编辑:
这是一个例子:
人才表

+----+------+
| id | name |
+----+------+
|  1 | John |
|  2 | Bob  |
|  3 | Jack |
+----+------+

推桌

+----+----------+---------+
| id | talentId | offerId |
+----+----------+---------+
|  1 |        1 |     403 |
|  2 |        1 |      42 |
|  3 |        2 |     123 |
|  3 |        2 |     456 |
+----+----------+---------+

有了这些数据,带有where子句的查询只返回

+----+------+---------+
| id | name | offerId |
+----+------+---------+
|  1 | John | 403     |
+----+------+---------+

on有条件的返回所有想要的行

+----+------+---------+
| id | name | offerId |
+----+------+---------+
|  1 | John | 403     |
|  2 | Bob  | null    |
|  3 | Jack | null    |
+----+------+---------+

标签: sqlpostgresql

解决方案


不同之处在于当有匹配但在另一行时。最好用一个小例子来说明这一点。

考虑:

t1:

x      y
1      abc
1      def
2      xyz

t2:

x      y
1      def

然后left join版本返回所有三行t1

select *
from t1 left join
     t2
     on t1.x = t2.x and t1.y = t2.y;

where子句版本中的过滤:

select *
from t1 left join
     t2
     on t1.x = t2.x
where t2.y = 'abc' or t2.y is null;

只返回一行。返回的行是1/ abcx = 2匹配t2. 所以,t2.y不是null。它也不'abc'是。所以它被过滤掉了。

是一个 db<>fiddle。


推荐阅读