简体   繁体   English

对于 mysql 中的字符串列类型,NOT IN 未按预期工作

[英]NOT IN is not working as expected for string column type in mysql

I found something weird between NOT IN and IN where I use a string type column.我在使用字符串类型列的 NOT IN 和 IN 之间发现了一些奇怪的东西。 It works fine for IN but not for NOT IN.它适用于 IN 但不适用于 NOT IN。 Though both works (NOT IN and IN) for integer type column虽然两者都适用于整数类型列(NOT IN 和 IN)

SELECT * FROM `table1` t1 where t1.email not in (select t2.email from `table2` t2)

doesn't return any result from t1 which exist in t2 though it should as there are eligible records whereas不从 t1 返回任何存在于 t2 中的结果,尽管它应该有符合条件的记录,而

SELECT * FROM `table1` t1 where t1.email in (select t2.email from `table2` t2)

returns the records from t1 which are in t2.返回 t1 中 t2 中的记录。

Here is a simple example to explains this appearance which also occurs in other DBMS like SQL Server and Oracle.下面是一个简单的例子来解释这种外观,它也发生在其他 DBMS 中,如 SQL Server 和 Oracle。

Assume that假使,假设

select t2.email from `table2` t2

returns返回

+-------------+
| email       |
+-------------+
| 111@abc.com |
| 222@abc.com |
| NULL        |
+-------------+

When execute执行时

SELECT * FROM `table1` t1 where t1.email not in (select t2.email from `table2` t2)

MySQL translates it into MySQL将其翻译成

SELECT * FROM `table1` t1 
where 
t1.email <> '111@abc.com' AND t1.email <> '222@abc.com' AND t1.email <> NULL

The where clause always returns NULL because any value compare to NULL returns NULL and any boolean value do AND operation with NULL also returns NULL . where子句总是返回NULL因为任何与NULL比较的NULL返回NULL并且任何布尔值对NULL进行AND操作也返回NULL Therefore, the whole SQL query as shown above always return non record.因此,如上所示的整个 SQL 查询总是返回非记录。

Similarly,相似地,

SELECT * FROM `table1` t1 where t1.email in (select t2.email from `table2` t2)

will be translated into将被翻译成

SELECT * FROM `table1` t1 
where 
t1.email = '111@abc.com' OR t1.email = '222@abc.com' OR t1.email <> NULL

The value of t1.email <> NULL is NULL , which will be ignored if any other comparation is TRUE . t1.email <> NULL值为NULL ,如果任何其他比较为TRUE ,它将被忽略。

Modifying query to below worked.将查询修改为以下有效。

SELECT * 
  FROM table1 t1 
 WHERE t1.email NOT IN ( SELECT t2.email 
                           FROM table2 t2 
                          WHERE t2.email IS NOT NULL )

Since table2's email column value was NULL for one row which was returning no records.由于 table2 的 email 列值对于没有返回记录的一行是NULL

Don't use NOT IN with subqueries.不要NOT IN子查询中使用NOT IN The reason is simple: it does not handle NULL values as a person would expect them to be handled.原因很简单:它不会像人们期望的那样处理NULL值。

Instead, just get used to using NOT EXISTS :相反,只需习惯使用NOT EXISTS

SELECT t1.*
FROM `table1` t1 
WHERE NOT EXISTS (SELECT 1
                  FROM `table2` t2
                  WHERE t1.email= t2.email 
                 ) ;

Why does this not work as expected?为什么这不能按预期工作? This is because of how SQL defines NULL values.这是因为 SQL 如何定义NULL值。 They have the semantics of an "unknown" value rather than a "missing" value.它们具有“未知”值而不是“缺失”值的语义。

Consider the following conditions:考虑以下条件:

  • 1 IN (1, 2) -- evaluates to true 1 IN (1, 2) -- 评估为真
  • 3 IN (1, 2) -- evaluates to false 3 IN (1, 2) -- 评估为假

NULL s do not affect this, because it is an exact match: NULL不影响这个,因为它是一个完全匹配:

  • 1 IN (1, 2, NULL) -- evaluates to true 1 IN (1, 2, NULL) -- 评估为真
  • 3 IN (1, 2, NULL) -- evaluates to NULL, which is treated as false 3 IN (1, 2, NULL) -- 计算结果为 NULL,被视为假

But NULL s do affect NOT INNULL确实影响NOT IN

  • 1 NOT IN (1, 2, NULL) -- evaluates to false 1 NOT IN (1, 2, NULL) -- 计算结果为假
  • 3 NOT IN (1, 2, NULL) -- evaluates to NULL because NULL is "unknown" 3 NOT IN (1, 2, NULL) -- 评估为 NULL,因为 NULL 是“未知”

The key is that NULL does not have a specific meaning -- it means "unknown".关键是NULL没有特定的含义——它的意思是“未知”。 So, NULL could be equal to 3. Hence, the result of the last expression is "unknown" (ie NULL ) rather than "true".因此, NULL可能等于 3。因此,最后一个表达式的结果是“未知”(即NULL )而不是“真”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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