繁体   English   中英

如何使用 SQL 窗口函数计算聚合的百分比

[英]How to use a SQL window function to calculate a percentage of an aggregate

我需要计算表格中各个维度的百分比。 我想通过使用窗口函数来计算分母来简化事情,但是我遇到了一个问题,因为分子也必须是一个聚合体。

举个简单的例子,看下表:

create temp table test (d1 text, d2 text, v numeric);
insert into test values ('a','x',5), ('a','y',5), ('a','y',10), ('b','x',20);

如果我只想计算 d1 中每一行的份额,则窗口函数可以正常工作:

select d1, d2, v/sum(v) over (partition by d1)
from test;

"b";"x";1.00
"a";"x";0.25
"a";"y";0.25
"a";"y";0.50

但是,我需要做的是计算 d1 中 d2 总和的总份额。 我正在寻找的输出是这样的:

"b";"x";1.00
"a";"x";0.25
"a";"y";0.75

所以我试试这个:

select d1, d2, sum(v)/sum(v) over (partition by d1)
from test
group by d1, d2;

但是,现在我收到一个错误:

ERROR:  column "test.v" must appear in the GROUP BY clause or be used in an aggregate function

我假设这是因为它抱怨在分组子句中没有考虑窗口函数,但是无论如何不能将窗口函数放在分组子句中。

这是使用 Greenplum 4.1,它是 Postgresql 8.4 的一个分支并共享相同的窗口函数。 请注意,Greenplum 不能进行相关子查询。

我想你正在寻找这个:

SELECT d1, d2, sum(v)/sum(sum(v)) OVER (PARTITION BY d1) AS share
FROM   test
GROUP  BY d1, d2;

产生请求的结果。

聚合函数之后应用窗口函数。 sum(sum(v)) OVER ...的外部sum()是一个窗口函数(附加OVER ...子句),而内部sum()是一个聚合函数。

实际上等同于:

WITH x AS (
   SELECT d1, d2, sum(v) AS sv
   FROM   test
   GROUP  BY d1, d2
   )
SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share
FROM   x;

或(无 CTE):

SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share
FROM  (
   SELECT d1, d2, sum(v) AS sv
   FROM   test
   GROUP  BY d1, d2
   ) x;

或者@Mu 的变体。

旁白:Greenplum 在 4.2 版中引入了相关子查询。 请参阅发行说明。

你需要用窗口函数来做这一切吗? 听起来您只需d1d2对结果进行分组,然后将总和相加:

select d1, d2, sum(p)
from (
    select d1, d2, v/sum(v) over (partition by d1) as p
    from test
) as dt
group by d1, d2

这给了我这个:

 d1 | d2 |          sum           
----+----+------------------------
 a  | x  | 0.25000000000000000000
 a  | y  | 0.75000000000000000000
 b  | x  | 1.00000000000000000000

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM