When the condition by one table is placed in WHERE then it is applied after the joining.
When the condition by one table is placed in ON then it is applied during (but this looks like before) the joining.
CREATE TABLE t1
SELECT 1 id, 1 val UNION ALL
SELECT 2, 2 UNION ALL
SELECT 3, 3;
CREATE TABLE t2
SELECT 1 id, 1 val UNION ALL
SELECT 2, 2 UNION ALL
SELECT 4, 4 UNION ALL
SELECT NULL, 5;
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id;
id |
val |
id |
val |
1 |
1 |
1 |
1 |
2 |
2 |
2 |
2 |
3 |
3 |
null |
null |
First SELECT joins the tables without additional condition.
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL;
id |
val |
id |
val |
3 |
3 |
null |
null |
Second SELECT contains additional condition by right table in WHERE. This condition is applied after joining, i.e. to the rowset which is returned by first SELECT, and only one row is returned.
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
AND t2.id IS NULL;
SELECT * FROM t2 WHERE t2.id IS NULL;
id |
val |
id |
val |
1 |
1 |
null |
null |
2 |
2 |
null |
null |
3 |
3 |
null |
null |
Third SELECT contains additional condition by right table in ON, which is applied to the source table. This is shown additionally.
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.id > 1;
id |
val |
id |
val |
2 |
2 |
2 |
2 |
3 |
3 |
null |
null |
Forth SELECT contains additional condition by left table in WHERE. This condition is applied after joining, i.e. to the rowset which is returned by first SELECT, and only two rows is returned.
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
AND t1.id > 1;
SELECT * FROM t1 WHERE t1.id > 1;
id |
val |
id |
val |
1 |
1 |
null |
null |
2 |
2 |
2 |
2 |
3 |
3 |
null |
null |
Fifth SELECT contains additional condition by left table in ON, which is applied to the source table. This is shown additionally.
fiddle