2011-05-29 31 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