如何使用隐式 DISTINCT 创建聚合函数,如 sum?

m3a*_*smi 6 postgresql aggregate distinct

我们有一个 ERP 系统,它允许使用聚合(例如SUM(foo))但不允许使用 DISTINCT(例如SUM(DISTINCT foo).

是否可以创建一个聚合函数 ( SUM_DISTINCT),它返回与 相同的结果SUM(DISTINCT foo),所以SUM_DISTINCT(foo) = SUM(DISTINCT foo)

Jac*_*las 8

是否可以创建一个聚合函数 ( SUM_DISTINCT),它返回与 相同的结果SUM(DISTINCT foo),所以SUM_DISTINCT(foo) = SUM(DISTINCT foo)

是的,这是可能的 - 您需要一个User-defined Aggregate,例如:

create or replace function f_sum_distinct (numeric[], numeric) returns numeric[]
    language sql as $$
select $1||$2;
$$;

create or replace function f_sum_distinct_final (numeric[]) returns numeric 
    language sql as $$
select sum(v) from (select distinct unnest($1) v) z;
$$;

create aggregate sum_distinct(numeric)
( sfunc     = f_sum_distinct
 ,stype     = numeric[]
 ,finalfunc = f_sum_distinct_final
);

with w(v) as (select 2 union all select 2 union all select 3)
select sum(v) "Plain SUM", sum(distinct v) "SUM(DISTINCT)", sum_distinct(v) "SUM_DISTINCT" from w;

/*
|Plain SUM|SUM(DISTINCT)|SUM_DISTINCT|
|--------:|------------:|-----------:|
|        7|            5|           5|
*/
Run Code Online (Sandbox Code Playgroud)

dbfiddle在这里

请注意(感谢@Erwin),该性能将比内置聚合很多。如果这很重要,您将不得不考虑用 C 编写辅助函数,这更像是一项任务。

  • 应该提到的是,性能比 `sum(DISTINCT foo)` 慢得多。我对一个有 46k 行的表进行了快速测试。正如预期的那样,`sum_distinct(foo)` 比 `sum(DISTINCT foo)` 慢 1000 倍。并且它不能很好地扩展,即使用更大的表会变得更糟。IOW:除非绝对必须,否则不要使用它。 (2认同)