为何NULL在聚合函数与标量函数中的处理方式不同?
为什么NULL在聚合函数与普通标量函数中的处理逻辑不同?
先看两个典型示例:
select greatest(1, val) from unnest([null]) as val -- 返回结果:null
select sum(val) from unnest([1, null]) as val -- 返回结果:1
这种差异主要源于语义设计目标、实用性权衡和SQL的历史演进:
语义层面的本质区别
标量函数(比如greatest)是对确定的输入组合做计算,NULL代表“未知值”,当你拿一个已知值和未知值比大小,结果自然也是未知——毕竟你没法确定未知值到底比1大还是小,所以返回NULL是符合“未知”语义的。
而聚合函数(比如sum)是对一组数据做汇总,它的设计目标是尽可能给出有意义的统计结果。如果因为一组数据里有几个未知值就直接返回NULL,大部分场景下都不实用——毕竟用户要的是现有已知数据的总和,而不是因为存在未知就彻底放弃统计。实用性的权衡选择
SQL标准制定时,考虑了实际业务场景的需求:- 标量函数如果强行忽略NULL返回已知值,会违背“未知”的语义,比如
greatest(1, NULL)返回1的话,相当于默认NULL比1小,但这是没有依据的,可能误导后续逻辑。 - 聚合函数如果严格遵循“有未知则结果未知”,那大部分包含NULL的数据集都没法得到有效统计结果,这显然不符合用户使用聚合函数的核心诉求——汇总有效数据。
- 标量函数如果强行忽略NULL返回已知值,会违背“未知”的语义,比如
历史演进的惯性
早期SQL的设计就确立了这个规则,后续的数据库系统也延续了这个标准。比如最早的关系型数据库系统(如IBM的System R)就区分了标量运算和聚合运算对NULL的处理,这个设计被ANSI SQL标准采纳后,就成为了所有数据库遵循的规范。
简单来说,两者的差异是语义严谨性和实际实用性之间的平衡:标量函数优先保证语义准确,聚合函数优先保证结果有用。
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

