postgresql:参数化聚合类型?

时间:2011-05-29 19:46:40

标签: postgresql aggregate-functions plpgsql

我需要提供一些存储过程,这些过程返回在数据库中选择的值上运行的聚合函数的结果,即平均值,总和,最小值,最大值等。值的选择总是在类似的方式。

我的第一个天真实现包括每个聚合函数类型的一个存储过程,例如: get_avg(...),get_sum(...)。这些功能显然共享了很多重复的代码。我想知道是否有办法将聚合类型移动到参数左右,然后只使用一个存储过程,例如get_aggregate(aggr_type,...)

就pl / pgsql实现而言,我能想到的唯一方法是选择应该进入聚合的值,然后在aggr_type == ... / else子句中使用它们。是聚合类型。但这不是很灵活,只要需要支持新的聚合类型,就需要更改代码。

有没有办法在pl / pgsql中参数化函数的名称? 你能想到一种我看不到的方法吗?

1 个答案:

答案 0 :(得分:1)

从技术上讲,您可以在plpgsql函数中使用execute语句:

return query
execute $x$
select id, $x$ || quote_ident(agg_func) || $x$(col)::numeric as agg
from bar
$x$;

(参见下面的正确例子)。问题是,这将意味着在每次调用时解析/规划您的查询。

有时,更好的选择是创建一个创建各种所需功能的功能。像这样:

create or replace function generate_agg_functions(_table regclass) returns void as $$
declare
  _agg_type text[] = '{sum, avg}';
  _ret_type regtype[] = '{numeric, numeric}';
  rec record;
begin
  for rec in select _agg_type[i] as agg_type, _ret_type[i] as ret_type
  from generate_subscripts(_agg_type, 1) i
  loop
  execute $x$
  create or replace function $x$ || quote_ident(_table || '_' || rec.agg_func) || $x$()
    returns table (id int, $x$ || quote_ident(rec.agg_type) || ' ' || ret_type || $x$)
  $def$
  begin
    return query
    select id,
           $x$ || quote_ident(rec.agg_type) || $x$(col)::$x$ || rec.ret_type || $x$
             as $x$ || quote_ident(rec.agg_type) || $x$
    from $x$ || _table || $x$;
  end;
  $def$ language plpgsql stable;
  $x$;
  end loop;
end;
$$ language plpgsql;

编写起来有点棘手,但最终不会在不影响单个聚合的性能的情况下复制代码。