【问题标题】:PortgreSQL - Function to calculate percentagesPostgreSQL - 计算百分比的函数
【发布时间】:2013-10-27 16:44:07
【问题描述】:

在 postgresql 中,如果我想要百分比,我就写:

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 不在函数内进行总结。

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

【问题讨论】:

  • 您不能将某些聚合函数或窗口函数撕成盒装的 sql 函数。不支持。
  • 是的,我意识到这一点。但我觉得奇怪的是,没有(简单的)方法来构建一个计算百分比的函数。我很确定很多人会使用它。它本身很有用,可以包含在更复杂的结构中。
  • @user2895901 - 这可能很好,但这不是通常的用户请求。但这并非不可能 - 如果我理解,您将创建一个自定义窗口函数。您可以用 C 编写自己的,也可以使用 PL/v8 语言,支持自定义窗口函数pgxn.org/dist/plv8/1.3.0/doc/plv8.html
  • 好的。这听起来像是要走的路。在提出问题之前,我将自定义聚合视为一种可能的解决方案。丹尼斯在他的回答中提到了这一点,但我想我真正需要的是自定义窗口函数。谢谢。

标签: postgresql aggregate-functions percentage


【解决方案1】:

要调试您的函数,请在文本文件中编写带有任意参数的查询,然后使用 psql 运行它:

\i ./myfunc.sql

myfunc.sql 的内容是:

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

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

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

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


查看新的详细信息,请注意,如果您准备在函数中运行的查询,您应该始终得到 1 -- 零栏。

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

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

【讨论】:

  • 谢谢。我不知道这个。
【解决方案2】:

我通过 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;

【讨论】:

    猜你喜欢
    • 2017-05-13
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 2023-02-11
    • 2017-08-14
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多