Consider the following table:
mysql> select * from phone_numbers; +-------------+------+-----------+ | number | type | person_id | +-------------+------+-----------+ | 17182225465 | home | 1 | | 19172225465 | cell | 1 | | 12129876543 | home | 2 | | 13049876543 | cell | 2 | | 15064223454 | home | 3 | | 15064223454 | cell | 3 | | 18724356798 | home | 4 | | 19174335465 | cell | 5 | +-------------+------+-----------+
I’m trying to find those people who have home phones but not cells.
This query works:
mysql> select h.* -> from phone_numbers h -> left join phone_numbers c -> on h.person_id = c.person_id -> and c.type = 'cell' -> where h.type = 'home' -> and c.number is null; +-------------+------+-----------+ | number | type | person_id | +-------------+------+-----------+ | 18724356798 | home | 4 | +-------------+------+-----------+
but this one doesn’t:
mysql> select h.* -> from phone_numbers h -> left join phone_numbers c -> on h.person_id = c.person_id -> and h.type = 'home' -> and c.type = 'cell' -> where c.number is null; +-------------+------+-----------+ | number | type | person_id | +-------------+------+-----------+ | 19172225465 | cell | 1 | | 13049876543 | cell | 2 | | 15064223454 | cell | 3 | | 18724356798 | home | 4 | | 19174335465 | cell | 5 | +-------------+------+-----------+
The only difference between the two is the location of the h.type = 'home' condition – in the first it’s in the where clause and in the second it’s part of the on clause.
Why doesn’t the second query return the same result as the first?
In the second SQL, the condition h.type = ‘home’ is part of the outer join conditions, and is not a filter on the results. For all records where h.type=’cell’, the condition h.type = ‘home’ is FALSE and so no ‘matching’ c row is found – so c.number is null, which is your only filtering (WHERE) condition.
In pseudo-code your 2nd SQL works like this: