39

我有这个架构

create table t(id int, d date) 

insert into t (id, d) values (1, getdate()), 
                             (2, NULL)

做的时候

declare @mindate date    
select @mindate = min(d) from t

我收到警告

空值被聚合或其他 SET 操作消除

为什么以及我能做些什么呢?

4

5 回答 5

117

大多数情况下,您不应该对此采取任何措施。

  • 可以通过关闭来禁用警告,ansi_warnings但这会产生其他影响,例如如何处理除以零,并且当您的查询使用索引视图、计算列或 XML 方法等功能时,可能会导致失败。
  • 在某些有限的情况下,您可以重写聚合以避免它。egCOUNT(nullable_column)可以重写为,SUM(CASE WHEN nullable_column IS NULL THEN 0 ELSE 1 END)但这并不总是可以在不改变语义的情况下直接完成。

这只是SQL 标准中所需的信息性消息。除了向消息流添加不需要的噪音之外,它没有任何不良影响(除了意味着 SQL Server 不能绕过读取NULL行,这可能会产生开销,但禁用警告并不能在这方面提供更好的执行计划)

返回此消息的原因是 SQL 空值在大多数操作中都会传播。

SELECT NULL + 3 + 7返回NULL(关于NULL未知数量,这是有道理的,? + 3 + 7也是未知的)

SELECT SUM(N)
FROM   (VALUES (NULL),
               (3),
               (7)) V(N) 

返回10和忽略空值的警告。

然而,这些正是典型聚合查询所需的语义。否则,单个的存在NULL将意味着该列上所有行的聚合总是最终会产生NULL,这不是很有用。

下面哪个蛋糕最重?图片来源知识共享图像由我更改(裁剪和注释))

在此处输入图像描述

第三块蛋糕称重后,天平坏了,因此没有关于第四块蛋糕的信息,但仍然可以测量周长。

+--------+--------+---------------+
| CakeId | Weight | Circumference |
+--------+--------+---------------+
|      1 | 50     | 12.0          |
|      2 | 80     | 14.2          |
|      3 | 70     | 13.7          |
|      4 | NULL   | 13.4          |
+--------+--------+---------------+

查询

SELECT MAX(Weight)        AS MaxWeight,
       AVG(Circumference) AS AvgCircumference
FROM   Cakes 

退货

+-----------+------------------+
| MaxWeight | AvgCircumference |
+-----------+------------------+
|        80 |          13.325  |
+-----------+------------------+

尽管从技术上讲,不能肯定地说 80 是最重的蛋糕的重量(因为未知数可能更大),但上述结果通常比简单地返回未知数更有用。

+-----------+------------------+
| MaxWeight | AvgCircumference |
+-----------+------------------+
|         ? |          13.325  |
+-----------+------------------+

您很可能希望忽略 NULL,而警告只是提醒您注意这种情况正在发生。

于 2013-09-10T13:09:08.853 回答
4

@juergen 提供了两个很好的答案:

  • 使用抑制警告SET ANSI_WARNINGS OFF
  • 假设您想包含 NULL 值并将它们视为(比如说)使用select @mindate = min(isnull(d, cast(0 as datetime))) from t

但是,如果您想忽略 d 列为 null 的行并且不关心该ANSI_WARNINGS选项,则可以通过排除 d 设置为 null 的所有行来执行此操作,如下所示:

select @mindate = min(d) from t where (d IS NOT NULL)
于 2015-06-09T15:31:29.963 回答
3

我认为您可以在这种情况下忽略此警告,因为您使用了该MIN功能。

“除了 COUNT,聚合函数忽略空值”

请参阅聚合函数 (Transact-SQL)

于 2013-09-10T13:17:26.643 回答
2

在你的情况下应该min()返回什么作为最低值d

该错误通知您该min()函数未将记录考虑在内null

因此,如果它应该忽略这些NULL值并返回最低的现有日期,那么您可以忽略此警告。

如果您还想禁止此单个语句的警告,那么您可以这样做

set ansi_warnings off
select @mindate = min(d) from t
set ansi_warnings on

如果您希望NULL通过使用默认值来考虑值,那么您可以像这样设置默认日期值

select @mindate = min(isnull(d, cast(0 as datetime)))
from t
于 2013-09-10T12:50:50.003 回答
2

如果要使聚合考虑null值并按null您可以使用的方式处理结果:

SELECT IIF(COUNT(N) != COUNT(*), NULL, SUM(N)) as [Sum]
FROM   (VALUES (NULL),
               (3),
               (7)) V(N) 

null如果没有给出所有值,则返回。

于 2016-11-14T09:00:30.760 回答