不等于数字不包括 null SQL Server

问题描述 投票:0回答:1

我在 SQL Server 中有这个 SQL 查询作为上下文。

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 InstallerID <> 29
GROUP BY 
    O.OrderID

当我运行它时,除了

InstallerID
可以为 NULL 之外,一切都运行良好。我预计这并不重要,因为。我假设由于 NULL 不是 3 或 29,那么它将包含在结果中。但这个查询似乎遗漏了所有带有 NULL
InstallerID
的内容。我想知道为什么会这样。

这就是它的工作原理吗?如果是这样,我是否应该小心不要编写再次出现此错误的查询?如果这是真的,是否有实践或设计选择可以最好地处理或避免这种情况?

sql sql-server ssms
1个回答
0
投票

正如我在评论中提到的,

NULL
值不适用于相等运算符。当
SomeColumn != 3
的值为 SomeColumn 时,
3
将返回
UNKNOWN
,重要的是 isn't TRUE,因此该行会从结果集中省略。

NULL
进行比较时,您需要使用
IS NULL
IS DISTINCT FROM
(后者仅在 Azure 或 SQL Server 2022+ 上受支持)。例如
(SomeColumn != 3 OR SomeColumn IS NULL)
SomeColumn IS DISTINCT FROM 3

对于您的查询,结果如下((取消)评论适合您的解决方案):

USE FCMDB; --Connect to the correct DB, there's no need for 3 part naming here
GO

SELECT O.OrderID,
       SUM(P.Quantity) AS SprayGlueCans
FROM dbo.FcoOrders O
    JOIN dbo.FcoStyleGroups SG ON SG.OrderID = O.OrderID
    JOIN dbo.FcoProducts P ON P.StyleGroupID = SG.StyleGroupID
WHERE P.CatalogProductID = 12715
  AND O.Shipped = 1
  AND O.ShipDate >= '20230801'
  AND O.ShipDate < '20230901'
  AND (O.InstallerID NOT IN (3,29) OR O.InstallerID IS NULL)
  --AND O.InstallerID IS DISTINCT FROM 3 AND O.InstallerID IS DISTINCT FROM 29
GROUP BY O.OrderID;

您会注意到,当使用

NOT IN
时,我切换到
IS NULL
,并且我还将您针对
ShipDate
的条款更改为 SARGable。再次强调,正如评论中提到的,不要在
YEAR(O.ShipDate) = 2023
中使用像
WHERE
这样的子句,因为索引不能用于此类查询,这将导致性能不佳。

© www.soinside.com 2019 - 2024. All rights reserved.