<>的行为过滤空值

时间:2012-04-07 05:27:35

标签: sql sql-server sql-server-2008

嗨专家:我有一个名为tblAlarm的表,它有一些像这样的记录:

enter image description here

我有另一个表来确定用户看到什么消息:

enter image description here

现在我想编写一个查询来显示用户在消息确实已过期时没有看到的消息。(例如,它是BeginYear和EndYear之间的年份,依此类推......)。我写这个查询:

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)

然后它返回:

enter image description here

但是如果我在最后一行取消评论,它就不会返回任何记录。如何判断用户还没有看到哪些消息?

感谢

2 个答案:

答案 0 :(得分:6)

将NULL与值进行比较的结果是UNKNOWN。过滤条件仅选择条件求值为TRUE的行,因此未选择条件求值为FALSE或UNKNOWN的行。

IS NULLIS NOT NULL测试不同,总是产生TRUE或FALSE答案。你也不能写column = NULLcolumn != NULL(至少,SQL标准不允许这样做;一些SQL方言可能)。

你的条件是:

AND (tua.UserID <> 128 AND tua.UserID IS NULL)
  • 如果tua.UserID的值为NULL,则第二项计算结果为TRUE,但第一项将计算为UNKNOWN,而UNKNOWN和TRUE为UNKNOWN,这不是TRUE,因此行未被选中。

  • 如果tua.UserID的值不为NULL,则第二项的计算结果为FALSE,因此整体条件的计算结果为FALSE,因此未选中该行。

因此,当您添加条件时,没有选择任何内容,如您所观察到的那样。

更典型的是,您的情况可能是以下两种情况之一:

AND (tua.UserID <> 128 AND tua.UserID IS NOT NULL)

AND (tua.UserID <> 128 OR tua.UserID IS NULL)

第一种选择中的双重条件实际上是多余的。如果tua.UserID为NULL,则第一项将评估为UNKNOWN,因此整体条件不会为TRUE,并且不会选择该行。第二种选择非常有用。

答案 1 :(得分:0)

NULL”表示:“我不知道价值”。这并不意味着:“没有任何价值”。因此,如果您使用NULL-Value执行比较作为其参数之一,则结果可能是TRUEFALSE,具体取决于实际(但未知)值。但UNKNOWN不是比较的有效结果,因此在这种情况下输出为FALSE

当您放置比较运算符时=!=<<=>>=,{{1在两个值(字段或文字)之间,其中一个值为NULL,那么比较操作的结果总是 <>

您已使用过NULL值的两个特殊比较运算符:FALSEIS NULL。两者都不是二元运算符,而是一元运算符。这意味着,他们没有两个参数,只有一个参数。他们测试他们的参数是否为NULL值。

因此,如果IS NOT NULLtua.UserID,则NULL必须为tua.UserID <> 128。另一部分FALSEtua.UserID IS NULL,但TRUEFALSE AND TRUE,这会为所有行生成完整的WHERE-Condition FALSE