2011-05-29 28 views
0

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

我的第一个幼稚实现包括一个存储过程,每个聚集函数类型,例如, get_avg(...),get_sum(...)。这些功能显然有相当多的重复代码。我想知道是否有办法将聚合类型移动到一个参数中,然后只使用一个存储过程,例如get_aggregate(aggr_type,...)

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

是否有任何方法参数化pl/pgsql中的函数的名称? ayone能想到一种我看不到的方法吗?

回答

1

你可以从技术上讲,使用execute语句进行PLPGSQL功能:

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; 

写起来有点棘手,但最终不会重复代码而不影响单个聚合的性能。

+0

哇!我现在感觉像我还有很多东西要学习postgresql。也许现在如果aggr_type == .../else不再是一个糟糕的选项。感谢您的帮助队友! :-) – ssc 2011-05-30 13:13:28