patternsqlMajor
Why Is Null Ignored In Query Results
Viewed 0 times
whyignorednullqueryresults
Problem
I have a table with similar structure to the below, and a field has a
My expected returned result would be where
NULL value in it. When I query the table this record is not returned, it is omitted. How should the query be altered so that this record is returned?Declare @Fiesty Table
(
numberfour varchar(100)
,valid varchar(20)
)
Insert Into @Fiesty (numberfour, valid) Values
('1ACRELBS', NULL), ('4ACRELBS', 'Green'), ('17ACRELBS', 'White')
Select * FROM @Fiesty WHERE valid NOT IN ('Green', 'Blue', 'White')My expected returned result would be where
numberfour = 1ACRELBSSolution
SQL uses ternary (three-valued) logic and comparisons with
it expands to:
When
When comparing nulls, you can think this way. I don't know the exact value of
If the intention is to get in the result the rows where
or
There is also a
Test at dbfiddle.uk.
NULL are tricky, counter intuitive. Regarding the condition:WHERE valid NOT IN ('Green', 'Blue', 'White')it expands to:
WHERE valid <> 'Green' AND valid <> 'Blue' AND valid <> 'White'When
valid is NULL, all these 3 sub-conditions evaluate to UNKNOWN (neither TRUE nor FALSE). The whole condition evaluates to UNKNOWN as well and thus the row rejected (WHERE keeps only the rows that the condition evaluates to TRUE).When comparing nulls, you can think this way. I don't know the exact value of
valid so I can't be sure if it's going to be different to 'Green' or not. It might be and it might be not. The result is UNKNOWN.If the intention is to get in the result the rows where
valid IS NULL, you can use either:SELECT * FROM @Fiesty
WHERE valid IS NULL
OR valid NOT IN ('Green', 'Blue', 'White') ;or
EXISTS / EXCEPT (or NOT EXISTS / INTERSECT):SELECT f.* FROM @Fiesty AS f
WHERE EXISTS
( SELECT f.valid
EXCEPT
SELECT v.valid
FROM
( VALUES ('Green'), ('Blue'), ('White') )
AS v (valid)
) ;There is also a
NOT EXISTS way which is my opinion to be preferred to NOT IN, especially because the behaviour regarding nulls is more intuitive. (Notice also the similarity with the INTERSECT version):SELECT f.* FROM Fiesty AS f
WHERE NOT EXISTS
( SELECT *
FROM
( VALUES ('Green'), ('Blue'), ('White') )
AS v (valid)
WHERE v.valid = f.valid
) ;Test at dbfiddle.uk.
Code Snippets
WHERE valid NOT IN ('Green', 'Blue', 'White')WHERE valid <> 'Green' AND valid <> 'Blue' AND valid <> 'White'SELECT * FROM @Fiesty
WHERE valid IS NULL
OR valid NOT IN ('Green', 'Blue', 'White') ;SELECT f.* FROM @Fiesty AS f
WHERE EXISTS
( SELECT f.valid
EXCEPT
SELECT v.valid
FROM
( VALUES ('Green'), ('Blue'), ('White') )
AS v (valid)
) ;SELECT f.* FROM Fiesty AS f
WHERE NOT EXISTS
( SELECT *
FROM
( VALUES ('Green'), ('Blue'), ('White') )
AS v (valid)
WHERE v.valid = f.valid
) ;Context
StackExchange Database Administrators Q#166579, answer score: 20
Revisions (0)
No revisions yet.