Sql 获取警告:通过聚合或其他集合操作消除空值

Sql 获取警告:通过聚合或其他集合操作消除空值,sql,sql-server,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 我得到了警告 通过聚合或其他集合操作消除空值 为什么以及我能做些什么?在您的情况下,min()应该以d的最低值返回什么 该错

我有这个模式

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
我得到了警告

通过聚合或其他集合操作消除空值

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

在您的情况下,
min()
应该以
d
的最低值返回什么

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

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

如果您还希望抑制此单个语句的警告,则可以这样做

set ansi_warnings off
select @mindate = min(d) from t
set ansi_warnings on
select @mindate = min(isnull(d, cast(0 as datetime)))
from t
如果希望通过使用默认值来考虑
NULL
值,则可以像这样设置默认日期值

set ansi_warnings off
select @mindate = min(d) from t
set ansi_warnings on
select @mindate = min(isnull(d, cast(0 as datetime)))
from t

大多数情况下,你不应该对此采取任何行动

  • 可以通过关闭
    ansi_warnings
    来禁用警告,但当查询使用索引视图、计算列或XML方法等功能时,这会导致失败
  • 在某些有限的情况下,您可以重写聚合以避免它。e、 g.
    COUNT(nullable\u column)
    可以重写为
    SUM(当nullable\u column为NULL时,则为0,否则为1结束)
    ,但如果不更改语义,这并不总是可以直接执行
这只是一条信息。除了向消息流添加不必要的干扰外,它没有任何不良影响(除了意味着SQL Server不能绕过读取
NULL
行,这可能会导致错误,但禁用警告不会在这方面提供更好的执行计划)

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

SELECT NULL+3+7
返回
NULL
(将
NULL
视为一个未知量,这是有意义的,因为
?+3+7
也是未知的)

但是

返回
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  |
+-----------+------------------+

因此,您很可能希望忽略空值,而警告只是提醒您发生这种情况。

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

“除计数外,聚合函数忽略空值”


请参阅

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

  • 使用
    SET ANSI\u WARNINGS OFF
  • 假设您希望包括空值,并将它们视为(比如)使用
    select@mindate=min(isnull(d,cast(0为datetime)),从t
但是,如果您希望忽略d列为null的行,而不关心
ANSI_WARNINGS
选项,则可以通过排除d设置为null的所有行来完成此操作,如下所示:

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

如果要聚合,请考虑<代码> null <代码>值,并将结果作为<代码> null >,可以使用:

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

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

建议的“修复”将返回不正确的结果。它将表明最早的日期是
1900-01-01
(除非数据中的日期恰好早于该日期),如果
d
具有这两个值,如“1/1/2001”和“1/1/2012”,将会发生什么情况。这将返回“1/1/1900”作为最小值?因此,如果执行
select*from table where date>@mindate
,这将导致添加
时出现问题,其中d不为null
我收到了相同的警告。我不介意警告本身,但是,我需要SQL代理运行存储过程,当我这样做时,警告会导致代理作业失败。@Richie它不会使SQL代理作业失败。它将出现在作业历史记录中可见的输出中,当作业因其他原因失败时,您可能会看到该输出,因此假设原因是您的选项1具有其他副作用。选项3仅在单个聚合列的情况下有效。对于
选择min(d1),min(d2)
没有可用于执行此操作的where子句。你为什么关心这个消息?这只是信息。谢谢马丁。我的前两个选项只是总结了juergen之前的答案,以便形成一个平台,在此平台上介绍我的选项(3?)。是的,我的建议只有在选择的汇总(最小、最大、平均、总和等)列作为问题的OP时才有效。该消息可能只是信息性的,但当我看到它们时,它们总是让我质疑查询,这打破了我在手头工作中的注意力。这很好地解释了问题,并允许我愉快地继续忽略警告,因为这正是我所期望的。尽管我对多个服务器上的空传播感到恼火有时候,我想我从来没有真正质疑过背后的原因。任何能让我“呼呼”或涉及饼干的答案都得到了我的投票。我可能已经在谷歌上搜索了好几次这个错误,但这是迄今为止对这个问题的最好解释,以及它为什么会出现,以及什么时候重要。非常感谢。很好的解释!