【问题标题】:How to select count as a percentage over the total in Oracle using any Oracle function?如何使用任何 Oracle 函数在 Oracle 中选择计数占总数的百分比?
【发布时间】:2011-07-07 15:34:38
【问题描述】:

我有一个 SQL 语句,它计算结束日期为空的活动包的总行数。我目前正在使用(x/y) * 100

SELECT (SELECT COUNT(*) 
          FROM packages 
         WHERE end_dt IS NULL) / (SELECT COUNT(*) 
                                    FROM packages) * 100 
  FROM DUAL;

我想知道是否有一种方法可以利用任何 Oracle 函数来更轻松地表达这一点?

【问题讨论】:

    标签: sql oracle aggregate-functions


    【解决方案1】:

    没有我知道的功能,但您可以简单地查询:

    SELECT SUM(CASE WHEN p.end_dt IS NULL THEN 1 ELSE 0 END) / COUNT(*) * 100
      FROM PACKAGES p
    

    【讨论】:

    • @OMG:我认为你想要 SUM,而不是 COUNT,然后翻转 1 和 0(或者说不是 null)
    • 嗨 Gerrat,是的,SUM 是正确的,但 1 和 0 是正确的。谢谢!
    • @OMG Ponies:或者您可以将 ELSE 部分更改为 ELSE NULL(或省略它)。
    • 另外,请尝试(a * 100.0) / b 将隐式强制转换为非整数类型,并避免舍入错误。
    • @OMG Ponies:你是对的,但是聚合处理 NULL 有点不同:它们只是忽略它们。无论如何,我的意思是将ELSE NULL 与 COUNT 一起使用,而不是与 SUM 一起使用。当条件满足时,CASE 将返回一个值,否则将返回 NULL。因此,COUNT 将仅计算满足条件时的出现次数。
    【解决方案2】:

    所以,基本上公式是

    COUNT(NULL-valued "end_dt") / COUNT(*) * 100
    

    现在,COUNT(NULL-valued "end_dt") 在语法上是错误的,但它可以表示为 COUNT(*) - COUNT(end_dt)。所以,公式可以是这样的:

    (COUNT(*) - COUNT(end_dt)) / COUNT(*) * 100
    

    如果我们稍微简化一下,我们会得到:

    SELECT (1 - COUNT(end_dt) * 1.0 / COUNT(*)) * 100 AS Percent
    FROM packages
    

    * 1.0 位将COUNT 的整数结果转换为非整数值,因此除法也为非整数。

    上面的句子和脚本的相应部分原来是完全垃圾。与其他一些数据库服务器不同,Oracle 不执行整数除法,即使两个操作数都是整数。 This doc page 没有暗示除法运算符的这种行为。

    【讨论】:

    • +1,但是... 需要转换 a/b 以使用非整数类型? (无论是隐式还是显式)
    • @Dems:你可能是对的。我确信 SQL Server 肯定需要这个。我会修改我的答案。
    • 100.0 - (100.0 * COUNT(end_dt) / COUNT(*))?
    • @Dems:啊,我在那个公式和我最终发布的那个公式之间左右为难。 也许你的稍微好一点。 :)
    • Oracle 10g 在有或没有额外的 1.0 乘法因子的情况下产生相同的答案。
    【解决方案3】:

    原来的帖子有点长,但这应该可以使用,使用自 Oracle 8i 以来可用的函数“ratio_to_report”:

    SELECT
      NVL2(END_DT, 'NOT NULL', 'NULL') END_DT,
      RATIO_TO_REPORT(COUNT(*)) OVER () AS PCT_TOTAL
    FROM
      PACKAGES
    GROUP BY
      NVL2(END_DT, 'NOT NULL', 'NULL');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-17
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 2020-03-27
      • 1970-01-01
      相关资源
      最近更新 更多