【问题标题】:aggregate of an empty result set空结果集的聚合
【发布时间】:2011-06-29 16:52:13
【问题描述】:

我希望空结果集的聚合为 0。我尝试了以下方法:

SELECT SUM(COALESCE(capacity, 0))
  FROM objects
 WHERE null IS NOT NULL;

结果:

sum 
-----

(1 row)

子问题:使用SUM(NVL(capacity, 0)),上述方法不能在Oracle 中工作吗?

【问题讨论】:

    标签: sql postgresql aggregate-functions


    【解决方案1】:

    来自the documentation page 关于聚合函数:

    需要注意的是,除了count,这些函数在没有选择行时返回空值。特别是,sum of no rows 返回 null,而不是预期的零。 coalesce 函数可用于在必要时将零替换为 null。

    因此,如果您想保证返回值,请将COALESCE 应用于SUM结果,而不是其参数:

    SELECT COALESCE(SUM(capacity), 0) …
    

    至于 Oracle 的“子问题”,我在官方文档页面(尤其是the one for 10.2)上找不到任何 NULL 的概念,但另外两个来源是明确的:

    也就是说,您无需将 NVL 应用于capacity。 (但是,就像 PostgreSQL 中的 COALESCE 一样,您可能希望将其应用于 SUM。)

    【讨论】:

    • 不应该是to substitute null for zero而不是引用to substitute zero for null吗?虽然我不是母语人士。
    • @VlastimilOvčáčík:我也不是。希望在文档中写这段话的人是! :) 说真的,那句话是正确的英语。 “用 A 代替 B”与“用 A 代替 代替 B”的含义相同。英语语法 - 去看看!
    • 你是right!但这很棘手。
    【解决方案2】:

    问题是,聚合总是返回一行,即使没有聚合任何行(就像您的查询中的情况一样)。您对没有行的表达式求和。因此你得到的 null 值。

    试试这个:

    select coalesce(sum(capacity),0)
    from objects
    where false;
    

    【讨论】:

    • 您可以使用 coalesce(sum(capacity),0) 简化它,因为 sum() 将忽略 NULL 值。
    • @peufeu:是的,但如果他的实际查询使用左连接,则 null + 任何内容都会产生 null,就像 sum 与可能为 null 的字段一样。
    • peufeu 是对的。 SUM 中的合并是多余的。看我答案的代码模拟
    • 是的。我仍然在这里和那里混淆。在 pg8 中将某些东西调试到 sum(round(stuff)) 的顺序造成的创伤。 :-)
    • sum() 的可空字段返回非空值的总和。 sum() 与通过添加包括 null 在内的所有值得到的结果不同...
    【解决方案3】:

    这样做:

    SELECT COALESCE( SUM(capacity), 0)
    FROM objects
    WHERE null IS NOT NULL;
    

    顺便说一下,SUM里面的COALESCE是多余的,即使容量为NULL,也不会使summary为null。

    也就是说:

    create table objects
    (
        capacity int null
    );
    
    insert into objects(capacity) values (1),(2),(NULL),(3);
    
    select sum(capacity) from objects;
    

    这将返回一个值 6,而不是 null。

    聚合函数内部的合并也是性能杀手,因为您的 RDBMS 引擎不能遍历所有行,它必须评估每一行的列,如果其值为空。我见过一点强迫症查询,其中所有的聚合查询都有一个合并,我认为原始开发人员有Cargo Cult Programming 的症状,查询方式非常sloooowww。我删除了 SUM 内部的合并,然后查询变得很快。

    【讨论】:

      【解决方案4】:

      虽然这篇文章很老了,但我想更新我在这种情况下使用的内容

      SELECT NVL(SUM(NVL(capacity, 0)),0)
      FROM objects
      WHERE false;
      

      这里的外部 NVL 避免了结果集中没有行的情况。内部 NVL 用于 null 列值,考虑 (1 + null) 的情况,它将导致 null。所以内部 NVL 也是必要的,否则在列的备用设置默认值 0 中。

      【讨论】:

      • SUM 函数忽略了NULL 值,因此内部的NVL 函数(或COALESCE,或其他方言中的ISNULL)是多余的。只有外层是必需的。
      猜你喜欢
      • 2019-02-20
      • 1970-01-01
      • 2018-06-24
      • 2015-05-26
      • 2019-07-26
      • 2021-03-30
      • 1970-01-01
      • 2021-11-07
      • 2016-10-02
      相关资源
      最近更新 更多