考虑两个表:
表1
id
1
2
3
表2
id, deleted
2, 0
3, 1
假设我要从表1中获得所有未在表2中标记为“已删除”的行,即行1和2。 考虑以下SQL(在MySQL中):
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted <> 1
此SQL显然仅返回id = 2的行。
我可以做这样的变态:
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE COALESCE(deleted, 0) = 0
然后我将获得第1行和第2行。
但是我想要一种更优雅的方式。 MySQL对布尔值,IS TRUE,IS NOT TRUE,IS FALSE,IS NOT FALSE进行了很好的检查,这些检查考虑了NULL值。所以考虑一下:
SELECT id, deleted, deleted IS NOT TRUE
FROM table1
LEFT JOIN table2 USING (id)
结果:
id, deleted, deleted IS NOT TRUE
1, NULL, TRUE
2, 0, TRUE
3, 1, FALSE
看起来不错,对吧?现在,如果我将其放入WHERE子句中:
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted IS NOT TRUE
哦,不!我又回到了第2行!
但是,如果我将条件放入HAVING子句中,它将开始工作:
SELECT id
FROM table1
LEFT JOIN table2 USING (id)
HAVING deleted IS NOT TRUE
我得到第1行和第2行。
完全令人困惑。好像是MySQL中的错误。
答案 0 :(得分:1)
正如我所怀疑的那样,正如@BillKarwin指出的那样,这是MySQL中的一个古老的2012年错误:(
“哪里var is not TRUE产生的值太少”(https://bugs.mysql.com/bug.php?id=67732)
答案 1 :(得分:0)
我认为您只想要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
);