将Postgres聚合函数转换为内联数组

时间:2015-12-07 14:52:23

标签: postgresql aggregate-functions standard-deviation

我被问到如何对一行中的变量值列表进行标准偏差。例如:

nodejs

select
  name, x, y, z, stddev (x, y, z)
from foo;

所以基本上就像select order_no, a, b, c, d, e, f, stddev (a, b, c, d, e, f) from foo; => minleast => max,我想以类似的方式将聚合的stddev变成" normal"功能

我已经能够创建一个自定义函数来根据标准公式计算标准差,但是如果可能的话,我不能帮助但更喜欢使用内置函数。我试过这个:

greatest

它抱怨道:

CREATE OR REPLACE FUNCTION std_deviation(variadic inputs numeric[])
  RETURNS numeric AS
$BODY$
DECLARE
  result numeric;
BEGIN

  select stddev (unnest (inputs))
  into result;

  return result;
end
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

此错误消息上没有流量不足,但我无法弄清楚如何将修复应用于我的简单功能。

或者,从一开始就有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

f :: (Int -> Bool) -> [Int] -> [Bool] f = map g :: Int -> Bool -> [Int] -> [Bool] g n b = map (\n' -> (n' == n) == b) λ> let ns = [42, 13, 42, 17] λ> f (== 42) ns [True,False,True,False] λ> g 42 True ns [True,False,True,False] λ> g 42 False ns [False,True,False,True] 子句中的设置返回函数(SRF) - 例如unnest - 是SQL标准的PostgreSQL特定扩展。并且通常不值得使用它(因为它不是它的样子)。此外, SRF不能在聚合函数中使用

使用SELECT子句中的这些SRF函数(并在需要时使用子选项):

FROM

如果你真的想为此编写一个函数,请使用SELECT name, x, y, z, (SELECT stddev(v) FROM unnest(ARRAY[x, y, z]) v) FROM foo 语言(它更清晰,PostgreSQL可以优化它们的使用):

SQL

答案 1 :(得分:1)

这似乎可以解决问题。

CREATE OR REPLACE FUNCTION public.std_deviation(VARIADIC inputs numeric[])
RETURNS numeric AS
$BODY$
DECLARE
result numeric;
BEGIN

with foo as (
select unnest (inputs) as bar
)
select stddev (bar)
into result
from foo;

return result;
end
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

答案 2 :(得分:0)

事实证明,pgnumerics已经有了这个功能。

-- test=# select pgnumerics.stdev('{1345,1301,1368,1322,1310,1370,1318,1350,1303,1299}');
--       stdev
-- ------------------
--  27.4639157198435
-- (1 row)

CREATE OR REPLACE FUNCTION pgnumerics.stdev (
  X double precision []
) RETURNS double precision
AS $$
DECLARE
  s double precision;
  N integer;
  i integer;
  xx double precision;
  sx double precision;
BEGIN
  N := array_upper(X,1) - array_lower(X,1) + 1;
  xx:= 0.0;
  sx:= 0.0;
  for i in 1..N loop
    xx:= xx + X[i]*X[i];
    sx:= sx + X[i];
  end loop;
  s := sqrt((N*xx - sx*sx) / (N*(N-1.0)));
  return s;
END;
$$ LANGUAGE 'plpgsql';

http://pgnumerics.projects.pgfoundry.org/