8

这是两个测试表的 sqlfiddle:http ://sqlfiddle.com/#!9/33361/3

tl;博士:为什么不!= 0包含NULL值的 SQL 查询?

我将加入这两个表。我想查看具有NULLintableB.field1或 a 1in 的行tableB.field1,但排除所有具有0in 的行tableB.field1

我认为这个查询(示例 6)应该给我这个结果,但它没有得到空记录。

SELECT * FROM tableA a
LEFT JOIN tableB b ON a.id = b.join_id
WHERE
b.field1 != 0;

我必须使用这个更长的查询(示例 4):

SELECT * FROM tableA a
LEFT JOIN tableB b ON a.id = b.join_id
WHERE
b.field1 != 0 OR b.field1 IS NULL;

只是好奇——MySQL 怎么不认为 N​​ULL 是 != 0?

当我将条件移动到 ON 子句时,我得到了一个意外的行:

mysql> SELECT * FROM tableA a
    -> LEFT JOIN tableB b ON a.id = b.join_id AND b.field1 != 0;
+------+--------+--------+---------+--------+--------+
| id   | field1 | field2 | join_id | field1 | field2 |
+------+--------+--------+---------+--------+--------+
|    1 | testA1 | testA1 |       1 | 1      | testB1 |
|    2 | testA2 | testA2 |    NULL | NULL   | NULL   |
|    3 | testA3 | testA3 |    NULL | NULL   | NULL   |
+------+--------+--------+---------+--------+--------+
3 rows in set (0.00 sec)
4

3 回答 3

8

为什么带有 != 0 的 SQL 查询不包含 NULL 值?

简短的回答:因为SELECT 0 != NULL回报(NULL)

更长的答案:根据MySQL 的文档

您不能使用算术比较运算符(例如 =、< 或 <>)来测试 NULL。

如果要在 Select 子句中包含 NULL,则必须借助“IS NULL”或“IFNULL”将其转换为算术表示。

您的 SQL 查询可以重写为:

SELECT * 
FROM tableA a
LEFT JOIN tableB b ON a.id = b.join_id
WHERE
    IFNULL(b.field1, -1) != 0;
于 2016-03-10T16:51:38.877 回答
4

来自 eggyal 的评论“或者只使用 MySQL 的 NULL 安全相等比较运算符,<= > —例如WHERE NOT b.field1 <=> 0。”

SELECT * FROM tableA a
LEFT JOIN tableB b ON a.id = b.join_id
WHERE NOT b.field1 <=> 0
;
于 2019-08-19T14:40:44.390 回答
1

使用外连接时,SQL 引擎使用空值表示组合集中没有数据。针对空值的相等性检查总是返回 false。

考虑:当 null = null then 1 else 0 end 这将始终产生 0!

您问:为什么带有 != 0 的 SQL 查询不包含 NULL 值?

在您的查询中,在引擎生成连接数据集之后应用 where 子句。
假设 A 的 ID 为 1,2,而 B 只有 1。

左连接的结果集将没有 where 子句:

  A.ID B.ID
    1  1
    2  NULL

您应用了 where 子句 b.field !=0

你得到

  A.ID B.ID
    1  1

空相等检查总是评估为 FALSE,因此第 2 行被排除,第 1 行被保留。

如果将过滤器移至连接条件,则在连接表之前应用限制。

SELECT * FROM tableA a
LEFT JOIN tableB b 
   ON a.id = b.join_id
  and b.field1 != 0;

  A.ID B.ID
    1  1
    2  NULL

并且由于第 2 行的 B 中没有记录,因此您会得到两行。

MySQL如何不认为NULL是!= 0?

Null 是一种特殊情况。与 null 的相等比较总是会产生错误。

is null,is not null是可用于检查值是否为空的两种方法。

您也可以用来where coalesce(b.field1,1) != 0确保返回第二条记录。尽管您最好将左连接中第二个表上的任何过滤器移动到连接条件。

于 2016-03-10T16:47:54.610 回答