简体   繁体   English

为什么 MySQL 的 IS TRUE、IS NOT TRUE、IS FALSE、IS NOT FALSE 的行为在 WHERE 和 HAVING 之间是不同的

[英]Why MySQL behavior of IS TRUE, IS NOT TRUE, IS FALSE, IS NOT FALSE is different between WHERE and HAVING

Consider two tables:考虑两个表:

table1表格1

id
1
2
3

table2表2

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):假设我想从 table1 中获取所有在 table2 中没有被标记为“删除”的行,即第 1 行和第 2 行。考虑以下 SQL(在 MySQL 中):

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted <> 1

This SQL obviously returns just row with id = 2.这个 SQL 显然只返回 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.然后我会得到第 1 行和第 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. MySQL 对布尔值进行了这些很好的检查,IS TRUE、IS NOT TRUE、IS FALSE、IS NOT FALSE 将 NULL 值考虑在内。 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:现在,如果我只是将其放入 WHERE 子句中:

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted IS NOT TRUE

Oh no!不好了! I get just row 2 again!我再次得到第 2 行!

However, if I put the condition into HAVING clause, it starts working:但是,如果我将条件放入 HAVING 子句中,它就会开始工作:

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
HAVING deleted IS NOT TRUE

I get row 1 and 2.我得到第 1 行和第 2 行。

Totally baffling.完全莫名其妙。 Seems like a bug in MySQL.似乎是 MySQL 中的一个错误。

As I suspected and as pointed out by @BillKarwin, this is an old 2012 bug in MySQL :(正如我怀疑和@BillKarwin 指出的那样,这是 MySQL 中的一个旧的 2012 错误:(

"WHERE var IS NOT TRUE yields too little" ( https://bugs.mysql.com/bug.php?id=67732 ) “WHERE var IS NOT TRUE 产量太少”( https://bugs.mysql.com/bug.php?id=67732

I think you just want NOT EXISTS :我想你只是想要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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM