【问题标题】:% of total calculation without subquery in PostgresPostgres 中没有子查询的总计算百分比
【发布时间】:2015-05-12 02:17:36
【问题描述】:

我正在尝试创建一个“总百分比”列,并且当前使用没有问题的子查询:

SELECT ID, COUNT(*), COUNT(*) / (SELECT COUNT(*)
FROM DATA) AS % OF TOTAL FROM DATA GROUP BY ID;

|  ID  | COUNT | % OF TOTAL |
|  1   |  100  |    0.10    |
|  2   |  800  |    0.80    |
|  3   |  100  |    0.10    |

但是,由于此问题范围之外的原因,我正在寻找是否有任何方法可以在不使用子查询的情况下完成此操作。本质上,应用程序使用 SQL 查询之外的逻辑来确定 WHERE 子句是什么,并将其注入到查询中。该逻辑不考虑上述子查询的存在,因此在返回并重建所有现有逻辑以解决这种情况之前,我想我会先看看是否有其他解决方案。

我试过用窗口函数来实现这个效果,但没有成功。

【问题讨论】:

  • 你可以使用像count(*) over ()这样的窗口——假设你实际上是在处理分组数据。但是,如果这是一个性能关键的查询,您可能还是希望使用子查询。

标签: sql postgresql aggregate-functions percentage


【解决方案1】:

使用窗口函数:

SELECT ID, COUNT(*),
       COUNT(*) / SUM(COUNT(*)) OVER () AS "% OF TOTAL"
FROM DATA
GROUP BY ID;

【讨论】:

  • 太好了,COUNT(*) 上的外包装正是我所需要的。你介意解释一下为什么需要这个包装器吗?
  • 在聚合查询中,您可以对聚合的结果求和。这种语法起初看起来很尴尬,但它确实很有意义。 count(*) 是为每一行定义的。 sum( . . .) over () 对所有行的参数求和。
【解决方案2】:
SELECT id, count(*) AS ct
     , round(count(*)::numeric
           / sum(count(*)) OVER (ORDER BY id), 2) AS pct_of_running_total
FROM   data
GROUP  BY id;

必须在窗口函数中添加ORDER BY,否则行的顺序是任意的。一开始我可能看起来是对的,但这可能会随时改变,而且不会发出警告。您似乎想按id 对行进行排序。

而且您显然不想要整数除法,这会截断小数位数。我转换为 numeric 并将结果四舍五入为两位小数,就像您的结果一样。

相关答案:

理解为什么这样有效的关键是SELECT 查询中的偶数序列:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    相关资源
    最近更新 更多