Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Not equal to number does not include null SQL Server

I have this SQL query in SQL Server for context.

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

When I run it everything works great except for the fact that the InstallerID can be NULL. I expected this to not matter because. I was under the assumption that since NULL is not 3 or 29 then it would be included in the results. But this query seems to leave out everything with a NULL InstallerID. I was wondering why this is so.

Is this just how it works? If so am I supposed to be careful to not write queries that have this mistake again? And if that is true are there practices or design choices to best handle or avoid this situation?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

As I mention in the comments, NULL values don’t work with equality operators. SomeColumn != 3 will return UNKNOWN when SomeColumn has a value of 3, which importantly isn’t TRUE, so the row is omitted from the result set.

When comparing to NULLs you need to use IS NULL or IS DISTINCT FROM (the latter is only supported in Azure or on SQL Server 2022+). For example (SomeColumn != 3 OR SomeColumn IS NULL) and SomeColumn IS DISTINCT FROM 3.

For your query, this results in the following ((un)comment the solution appropriate for you):

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;

You’ll notice I switch to a NOT IN when using IS NULL and I also change your clauses against ShipDate to be SARGable. Again, as mentioned in the comments, don’t uses clauses like YEAR(O.ShipDate) = 2023 in the WHERE, as indexes can’t be used for such queries, which will result in poor(er) performance.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading