web-dev-qa-db-ja.com

暗黙のDISTINCTを使用して、合計などの集計関数を作成するにはどうすればよいですか?

ERPシステムで集計を使用できます(例:SUM(foo))が、DISTINCT(例:SUM(DISTINCT foo))では使用できません。

SUM(DISTINCT foo)と同じ結果を返す集約関数(_SUM_DISTINCT_)を作成して、SUM_DISTINCT(foo) = SUM(DISTINCT foo)を作成することはできますか?

5
m3asmi

SUM(DISTINCT foo)と同じ結果を返す集約関数(_SUM_DISTINCT_)を作成して、SUM_DISTINCT(foo) = SUM(DISTINCT foo)を作成することはできますか?

はい、可能です。次のような ユーザー定義の集計 が必要です。

_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|
*/
_

dbfiddle ここ

ただし(@Erwinに感謝)、パフォーマンスは組み込みの集計よりも 非常に大幅に低下 になることに注意してください。これが問題になる場合は、Cでヘルパー関数を作成することを検討する必要があります。

私は問題を理解しているかどうかわかりません。再ハッシュするだけです...

_>>> 1+2+3+4+5
15
_

データをサンプリングします。

_CREATE TABLE foo
AS
  SELECT trunc(random()*5+1) AS x
  FROM generate_series(1,100);
_

次に、SUM(DISTINCT..)

_SELECT SUM(DISTINCT x)
FROM foo;
 sum 
-----
  15
_

@JackDouglasが独自のアグリゲートを個別にしたい場合は、アグリゲートを作成します ドキュメントから

SQLの集約関数呼び出しでは、DISTINCTおよび_ORDER BY_オプションを使用して、集約の遷移関数にどの行をどの順序で送るかを制御できます。 これらのオプションはバックグラウンドで実装されており、アグリゲートのサポート関数の問題ではありません。

これがDISTINCTとどう関係しているのかわかりません。

独自のsum()を実装する方法を知りたい場合は、ほぼ正確に(complexタイプを介して)ドキュメントに記載されています

_CREATE AGGREGATE mysum (numeric)
(
    sfunc = numeric_add,
    stype = numeric,
    initcond = '0'
);

SELECT mysum(x)
FROM ( VALUES (1),(5),(8),(8),(8) )
  AS t(x);

SELECT mysum(DISTINCT x)
FROM ( VALUES (1),(5),(8),(8),(8) )
  AS t(x);
_

特別な注意として、numeric_add(numeric,numeric)文書化されていない内部関数 です。これは_+_演算子で使用されますが、2つのnumericを必要とする任意のものを配置できます。

0
Evan Carroll