SQL Server中<>运算符不包含NULL的原因及处理方案咨询
问题原因
这是ANSI SQL标准定义的三值逻辑导致的,并非SQL Server独有特性。SQL中NULL代表“未知值”,任何与NULL的比较运算(包括<>、=、>、<等)都会返回UNKNOWN,而WHERE子句只会保留运算结果为TRUE的行,UNKNOWN会被直接过滤,所以InstallerID为NULL的记录被排除了。
解决方法
方法1:显式包含NULL的情况
在筛选条件中添加OR O.InstallerID IS NULL,注意用括号包裹相关条件,避免逻辑优先级错误:
SELECT O.OrderID, SUM(P.Quantity) AS SprayGlueCans FROM FCMDB.dbo.FcoOrders O JOIN FCMDB.dbo.FcoStyleGroups SG ON SG.OrderID = O.OrderID JOIN FCMDB.dbo.FcoProducts P ON P.StyleGroupID = SG.StyleGroupID WHERE P.CatalogProductID = 12715 AND O.Shipped = 1 AND MONTH(O.ShipDate) = 8 AND YEAR(O.ShipDate) = 2023 AND (O.InstallerID <> 3 AND O.InstallerID <> 29 OR O.InstallerID IS NULL) GROUP BY O.OrderID
方法2:用COALESCE转换NULL为默认值
如果业务中InstallerID不会出现某个特定值(比如-1),可以用COALESCE把NULL替换成该值,再用NOT IN筛选:
SELECT O.OrderID, SUM(P.Quantity) AS SprayGlueCans FROM FCMDB.dbo.FcoOrders O JOIN FCMDB.dbo.FcoStyleGroups SG ON SG.OrderID = O.OrderID JOIN FCMDB.dbo.FcoProducts P ON P.StyleGroupID = SG.StyleGroupID WHERE P.CatalogProductID = 12715 AND O.Shipped = 1 AND MONTH(O.ShipDate) = 8 AND YEAR(O.ShipDate) = 2023 AND COALESCE(O.InstallerID, -1) NOT IN (3, 29) GROUP BY O.OrderID
实践与设计建议
- 牢记SQL的三值逻辑:
TRUE/FALSE/UNKNOWN,WHERE、HAVING只保留TRUE的行,不要用常规二值逻辑的直觉判断NULL的比较结果。 - 处理可选字段时,若业务允许,可考虑用业务意义明确的默认值替代
NULL(比如用0代表无安装者),但需确保默认值不会和实际业务数据冲突。 - 当需要筛选排除特定值且包含NULL时,必须显式处理NULL,避免依赖
<>、NOT IN这类运算符自动包含NULL的错误假设。 - 对于SQL Server 2022及以上版本,可使用
IS NOT DISTINCT FROM运算符(符合ANSI SQL:2016标准),它会把NULL视为相等,比如NOT (O.InstallerID IS DISTINCT FROM 3)可以排除3但包含NULL,不过这种写法需要注意版本兼容性。
内容的提问来源于stack exchange,提问作者Daniel Kelsch
相关产品推荐
相关产品推荐

