获得警告:聚合或其他SET操作消除了空值

时间:2013-09-10 12:50:50

标签: sql sql-server

我有这个架构

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操作消除空值

为什么以及我该怎么办呢?

5 个答案:

答案 0 :(得分:89)

你也无能为力。

这只是一条信息性消息required in the SQL standard。它没有任何不良影响。

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

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

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

返回10以及忽略空值的警告。

然而,对于典型的聚合查询,这些正是您想要的语义。否则,单个NULL的存在将意味着所有行上该列的聚合总是会产生NULL,这不是非常有用。

下面最重的蛋糕是什么?Image SourceCreative Commons我的图像被修改(裁剪和注释)

enter image description here

在第三个蛋糕称重后,鳞片破裂,因此没有关于第四个蛋糕的信息,但仍然可以测量周长。

+--------+--------+---------------+
| 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,并且警告只会提醒您发生这种情况。

答案 1 :(得分:4)

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

  • 使用SET ANSI_WARNINGS OFF
  • 取消警告
  • 假设您要包含NULL值并将其视为(比方说)使用select @mindate = min(isnull(d, cast(0 as datetime))) from t

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

select @mindate = min(d) from t where (d IS NOT NULL)

答案 2 :(得分:3)

我认为您可以在使用MIN函数的情况下忽略此警告。

“除COUNT外,汇总函数忽略空值”

请参阅Aggregate Functions (Transact-SQL)

答案 3 :(得分: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

答案 4 :(得分:1)

如果您想让聚合考虑null值并将结果视为null,您可以使用:

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

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