[英]Why MySQL behavior of IS TRUE, IS NOT TRUE, IS FALSE, IS NOT FALSE is different between WHERE and HAVING
考虑两个表:
表格1
id
1
2
3
表2
id, deleted
2, 0
3, 1
假设我想从 table1 中获取所有在 table2 中没有被标记为“删除”的行,即第 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 中的一个错误。
正如我怀疑和@BillKarwin 指出的那样,这是 MySQL 中的一个旧的 2012 错误:(
“WHERE var IS NOT TRUE 产量太少”( https://bugs.mysql.com/bug.php?id=67732 )
我想你只是想要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
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.