这是两个测试表的平方:http://sqlfiddle.com/#!9/33361/3
tl; dr:为什么!= 0
的SQL查询不包含NULL
值?
我左边加入了两张桌子。我想查看NULL
中的tableB.field1
或1
中的tableB.field1
行,但排除{{1}中0
的所有行}}
我认为这个查询(例6)应该给我这个结果,但它不会得到空记录。
tableB.field1
我必须使用这个更长的查询(例4):
SELECT * FROM tableA a
LEFT JOIN tableB b ON a.id = b.join_id
WHERE
b.field1 != 0;
最好奇怪 - MySQL如何不考虑NULL!= 0?
当我将条件移动到ON子句时,我得到一个意外的行:
SELECT * FROM tableA a
LEFT JOIN tableB b ON a.id = b.join_id
WHERE
b.field1 != 0 OR b.field1 IS NULL;
答案 0 :(得分:6)
为什么带有!= 0的SQL查询不包含NULL值?
简短回答:因为SELECT 0 != NULL
返回(NULL)
更长的回答:根据MySQL's documentation
您不能使用算术比较运算符,例如=,<或<>测试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;
答案 1 :(得分:1)
使用外连接时,SQL引擎表示使用空值在组合集中缺少数据。对空值的等式检查总是返回false。
考虑:case null null = null然后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
来确保返回第二条记录。虽然你最好只是将左边连接中的第二个表上的任何过滤器移动到连接标记。
答案 2 :(得分:1)
From eggyal's comment:“或者只使用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
;