1

嗨专家:我有一个表叫做tblAlarm,它有一些这样的记录:

在此处输入图像描述

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

在此处输入图像描述

现在我想写一个查询来显示用户没有看到的消息如果消息没有过期。(例如它是 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)

它返回:

在此处输入图像描述

但是如果我取消注释最后一行,它不会返回任何记录。我如何确定哪些消息没有看到用户?

谢谢

4

2 回答 2

6

将 NULL 与值进行比较的结果是 UNKNOWN。筛选条件仅选择条件评估为 TRUE 的行,因此不选择条件评估为 FALSE 或 UNKNOWN 的行。

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

你的条件是:

AND (tua.UserID <> 128 AND tua.UserID IS NULL)
  • 如果 的值为tua.UserIDNULL,则第二项计算为 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,并且不会选择行。第二种选择非常有用。

于 2012-04-07T06:42:40.567 回答
0

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

当您在两个值(字段或文字)之间放置一个比较运算符,如=, !=, <, <=, >, >=,<>并且其中一个值为 NULL 时,该比较操作的结果始终 FALSE为。

您已经使用了两个用于 NULL 值的特殊比较运算符:IS NULLIS NOT NULL. 两者都不是二元运算符,而是一元运算符。这意味着,他们没有两个论点,而只有一个论点。他们测试他们的论点是否为 NULL 值。

所以,如果tua.UserIDNULLtua.UserID <> 128一定是FALSE。另一部分tua.UserID IS NULLTRUE, 但是FALSE AND TRUEFALSE,这使得FALSE所有行都具有完整的 WHERE-Condition。

于 2012-04-07T07:06:37.093 回答