Consider two tables:
table1
id
1
2
3
table2
id, deleted
2, 0
3, 1
Suppose I want to get all rows from table1 that have not been marked "deleted" in table2, ie row 1 and 2. Consider the following SQL (in MySQL):
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted <> 1
This SQL obviously returns just row with id = 2.
I can do a perversion like this:
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE COALESCE(deleted, 0) = 0
And then I'll get row 1 and 2.
But I wanted a more elegant way. MySQL has these nice checks for booleans, IS TRUE, IS NOT TRUE, IS FALSE, IS NOT FALSE that take NULL values into account. So consider this:
SELECT id, deleted, deleted IS NOT TRUE
FROM table1
LEFT JOIN table2 USING (id)
The result:
id, deleted, deleted IS NOT TRUE
1, NULL, TRUE
2, 0, TRUE
3, 1, FALSE
Looks great, right? now if I just put this into the WHERE clause:
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted IS NOT TRUE
Oh no! I get just row 2 again!
However, if I put the condition into HAVING clause, it starts working:
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
HAVING deleted IS NOT TRUE
I get row 1 and 2.
Totally baffling. Seems like a bug in MySQL.
As I suspected and as pointed out by @BillKarwin, this is an old 2012 bug in MySQL :(
"WHERE var IS NOT TRUE yields too little" ( https://bugs.mysql.com/bug.php?id=67732 )
I think you just want NOT EXISTS
:
SELECT t1.id
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table2 t2
WHERE t1.id = t2.id AND t2.is_deleted = 1
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.