提问人:David542 提问时间:6/10/2023 最后编辑:Thomas DickeyDavid542 更新时间:6/22/2023 访问量:195
为什么在聚合函数和标量函数中对 NULL 的处理方式不同?
Why is NULL handled differently in aggregate and scalar functions?
问:
让我们来看看以下两个问题:
select greatest(1, val) from unnest([null]) as val
# null
和:
select sum(val) from unnest([1, null]) as val
# 1
我的问题是为什么聚合函数和普通标量函数之间的处理方式不同?当然,当不计算值时,第二个查询更有用。但我认为如果它要返回而不是 .如果是一个“未知值”,那么两个函数不是都有一个假定的未知答案(即,),而不仅仅是后者吗?null
null
1
null
null
null
如果这有历史原因,那也很高兴知道。希望有人能阐明为什么两者之间存在差异。
答:
如果没有具体的引用,原因可能是由于比较函数(如)与计算函数(如 )。GREATEST
SUM
在 ANSI SQL 中,将任何值(使用 、、、 等运算符)进行比较时,应始终返回 unknown 或 。有趣的是,默认情况下,不同的 RDBMS 可能不会完全遵循此规则,因此可以重新调整非零行。请参阅 SQL Server 的 SET ANSI_NULLS
模式下的讨论。另请参阅 Postgres 的transform_null_equals
模式。<
>
=
<>
NULL
NULL
WHERE my_column <> NULL
另一方面,在 ANSI SQL 中也是如此,就像大多数聚合函数一样,除了忽略 s。因此,您观察到不同的行为。SUM
COUNT(*)
NULL
聚合函数应该跳过 null 值。以下是 SQL-92 标准的摘录:
<设置功能规范>
[...]
否则,让 TX 成为 将<值表达式>应用于 T 的每一行并消除 null 值。如果消除一个或多个 null 值,则 引发完成条件:警告 - 集合中消除的 null 值 功能。
另一方面,如果任何参数为 null¹,则该函数应返回 null。greatest
我的问题是为什么在聚合之间以不同的方式处理 null 函数和普通标量函数?
一般来说,如果标量函数的任何参数为 null²,则返回 null。以下是 Ask Tom 对这个完全相同的问题的看法,我个人同意答案中所说的一切:
汤姆说......
几乎所有的单行函数都返回 NULL,如果其中任何一个 要比较的输入为 null。
ops$tkyte%ORA10GR2> select round( 1.2, null ) from dual; ROUND(1.2,NULL) --------------- NULL
当你问“1、NULL、2 中最大的是什么——答案是”我们 不知道,因为 NULL 是未知的”
聚合被定义为“跳过空值”(ANSI 是这样说的)
但通常采用一组输入的函数将返回 NULL 当决定性输入为 NULL 时。
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm#i88893
如果调用带有 null 参数的 SQL 函数,则 SQL 函数 自动返回 null
¹ 在最大功能标准化之前很久就已经存在了不同的实现。如果任何参数为 null,MySQL 和 Oracle 返回 null;而 PostgreSQL 和 SQL Server 忽略 null 值。
² 相反,存在跳过 null 值的供应商特定标量函数。一个例子是 (MySQL, PostgreSQL, SQL Server) 函数,该函数旨在使用分隔符简化(可能为 null)字符串的连接。concat_ws
评论