2013-10-18 55 views
0

在PostgreSQL,如果我想的百分比我只是写:PortgreSQL - 函数来计算百分比

select x/sum(x) over() ... 

因为里面聚集函数不守规矩它不工作的功能。

我试图找到一个解决方案,但没有成功。 这是我真正需要的简单版本,但我相信这个问题的解决方案肯定会指向正确的方向。


更多的细节......

如果我创建这个简单的表:

create table ttt(v1 numeric, v2 numeric); 
insert into ttt values (2,1),(5,2),(10,4); 

如果我运行:

select v1/sum(v1) over() from ttt; --returns relative frequencies 

我得到:

select v1/sum(v1) over() from ttt; 
     ?column?   
------------------------ 
0.11764705882352941176 
0.29411764705882352941 
0.58823529411764705882 
(3 rows) 
现在

,如果我想创建一个函数,它做同样的事情,我会写:

create or replace function rfreq (double precision) 
returns double precision 
AS 
' 
select 
$1/sum($1) over() 
' 
LANGUAGE 'sql'; 

我得到:

select rfreq(v1) from bruto; 
rfreq 
------- 
    1 
    1 
    1 
(3 rows) 

PostgreSQL是不是一个函数内部总结。

有什么建议吗? 谢谢, 阿里。

+0

无法撕一些聚集函数或窗函数的给盒装SQL函数。它不受支持。 –

+0

是的,我意识到这一点。但我觉得奇怪的是,没有(简单的)方法来构建函数来计算百分比。我很确定很多人会使用它。它本身很有用,并且包含在更复杂的结构中。 – Ali

+1

@ user2895901 - 它可能很好,但它不是通常的用户请求。但这不是不可能的 - 如果我明白了,你会创建一个自定义窗口函数。你可以用C编写自己的文件,或者你可以使用PL/v8语言,它支持自定义窗口函数http://pgxn.org/dist/plv8/1.3.0/doc/plv8.html –

回答

0

我发现通过PL/R邮件列表的解决方案浏览。

百分比(或相对频率)可以用下面的代码postgres的计算:

CREATE OR REPLACE 
FUNCTION rel_freq(float8) 
RETURNS float8 AS 
$BODY$ 
    var <- as.vector(farg1) 
    return((var/sum(var))[prownum] 
$BODY$ 
LANGUAGE plr WINDOW; 
0

要调试功能,写在一个文本文件中的任意参数查询,然后使用PSQL运行它myfunc.sql的

\i ./myfunc.sql 

内容是:

select x/sum(y) over (...) ... 

这将允许您在将函数包装到函数中之前对其进行调试。

当您完成并且对少数样本的结果满意时,将其复制/粘贴到您的函数中,并在适用的情况下将硬编码测试值替换为参数。

至于优化它有参数时,我不知道有任何方法可以在Postgres函数中运行解释分析,但是您可以得到一个计划 - 我最清楚 - 与该函数将通过准备具有相同参数的语句来使用。所以你可以解释一下分析后者。


看到新的细节,注意,如果你准备,你在函数运行查询,你应该总是让1 - 零吧。

你在那里有一个错误,在某种意义上你需要保持状态从一个调用到下一个返回预期的结果。根据Pavel的建议,您实际上需要一个自定义聚合或自定义窗口功能。查看评论他建议的链接,以及:

http://www.postgresql.org/docs/current/static/xaggr.html

+0

谢谢。我不知道这个。 – Ali