Skip to content
Advertisement

difference between ‘where’ null and ‘on’ in a left join

Could someone explain to me why

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

yields less results than

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

The way I see it, it should boil down to the same result, but it doesn’t, and I’m not sure what I miss to get it.

first one does not contain rows that have no entry in the push table.

I’d expect them to be caught by the or "push"."offerId" is null.

EDIT:
here is an example:
talent table

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

push table

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

With this data, the query with the where clause returns only

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

while the one with the on condition returns all wanted rows

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

Advertisement

Answer

The difference is when there is a match but on another row. This is best shown with a small example.

Consider:

t1:

x      y
1      abc
1      def
2      xyz

t2:

x      y
1      def

Then the left join version returns all three rows in t1:

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

The filtering in the where clause version:

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

returns only one rows. The row that is returned is 1/abc. x = 2 matches in t2. So, t2.y is not null. And it is not 'abc' either. So it is filtered out.

Here is a db<>fiddle.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement