Reputation: 13479
Hi experts: I have a table Called tblAlarm
and it has some records like this:
I have another table for determine what user see what message:
Now I want to write a query to show Messages that user has not seen if message didinot expired.(for example it's year between BeginYear and EndYear and so on ...). I write this query:
SELECT *
FROM
tblAlarms LEFT OUTER JOIN tblUsersAlarms tua ON tblAlarms.Id=tua.MessageID
WHERE @CurrentYear BETWEEN tblAlarms.BeginYear AND tblAlarms.EndYear
AND @CurrentMonth BETWEEN tblAlarms.BeginMonth AND tblAlarms.EndMonth
AND @CurrentDay BETWEEN tblAlarms.BeginDay AND tblAlarms.EndDay
AND @CurrentHour * 60 + @CurrentMinute BETWEEN tblAlarms.BeginHour*60 + tblAlarms.BeginMinute AND tblAlarms.EndHour*60 + tblAlarms.EndMinute
--AND (tua.UserID <> 128 AND tua.UserID IS NULL)
and it returns :
but if I unComment last line it does not return any record.How I can determine what messages that users has not been seen?
thanks
Upvotes: 1
Views: 642
Reputation: 754820
The result of comparing a NULL with a value is UNKNOWN. A filter condition only selects rows where the conditions evaluate to TRUE, so rows where the condition evaluates to FALSE or UNKNOWN are not selected.
The IS NULL
and IS NOT NULL
tests are different and always produce a TRUE or FALSE answer. You also cannot write column = NULL
or column != NULL
(at least, the SQL standard does not allow that; some SQL dialects may).
Your condition is:
AND (tua.UserID <> 128 AND tua.UserID IS NULL)
If the value of tua.UserID
is NULL, then the second term evaluates to TRUE, but the first will then evaluate to UNKNOWN, and UNKNOWN and TRUE is UNKNOWN, which is not TRUE, so the row is not selected.
If the value of tua.UserID
is not NULL, then the second term evaluates to FALSE, so the overall condition evaluates to FALSE, and so the row is not selected.
Hence, when you add the condition, nothing is selected, as you observed.
More typically, your condition would be either of these two:
AND (tua.UserID <> 128 AND tua.UserID IS NOT NULL)
AND (tua.UserID <> 128 OR tua.UserID IS NULL)
The double condition in the first alternative is in fact redundant. If tua.UserID
is NULL, the first term will evaluate to UNKNOWN, so the overall condition would not be TRUE and the row would not be selected. The second alternative is quite useful.
Upvotes: 6
Reputation: 8527
"NULL
" means: "I don't know the value". It does not mean: "There can't be any value". So, if you execute a comparison with a NULL-Value as one of its arguments, the result could be TRUE
or FALSE
, depending on the real (but unknown) value. But UNKNOWN
is not a valid result of a comparison, so in this case the output is FALSE
.
When you put a comparision-operator like =
, !=
, <
, <=
, >
, >=
, <>
between two values (fields or literals), and one of this values is NULL then the result of that compare-operation is always FALSE
.
There are two special comparison-operators for NULL-Values, that you already used: IS NULL
and IS NOT NULL
. Both aren't binary operators, but unary operators. That means, they don't have two arguments, but only one. They test if their argument is a NULL-Value or not.
So, if tua.UserID
is NULL
, tua.UserID <> 128
must be FALSE
. The other part tua.UserID IS NULL
is TRUE
, but FALSE AND TRUE
is FALSE
, and this makes the complete WHERE-Condition FALSE
for all rows.
Upvotes: 0