Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用SQL窗口函数计算聚合的百分比_Sql_Postgresql_Aggregate Functions_Window Functions_Greenplum - Fatal编程技术网

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

如何使用SQL窗口函数计算聚合的百分比,sql,postgresql,aggregate-functions,window-functions,greenplum,Sql,Postgresql,Aggregate Functions,Window Functions,Greenplum,我需要计算表中各个维度的百分比。我想通过使用窗口函数来计算分母来简化事情,但是我有一个问题,因为分子也必须是聚合的 作为一个简单的示例,以下表为例: 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,

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

作为一个简单的示例,以下表为例:

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
我假设这是因为它抱怨grouping子句中没有考虑窗口函数,但是无论如何不能将窗口函数放在grouping子句中


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

是否需要使用窗口函数来完成所有操作?听起来您只需要将结果按
d1
d2
进行分组,然后求和:

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

我想你正在寻找这个:

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):

或者@Mu的变体


旁白:Greenplum在版本4.2中引入了相关子查询

啊,没错,这确实有效。我之所以不想使用子查询,是因为这实际上需要使用BI工具(Tableau),子查询会导致问题。啊,太棒了!这就是我想要的。有道理。文件对这些东西不是很清楚。
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;