PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Kumulatives Hinzufügen mit dynamischer Basis in Postgres

Erstellen Sie Ihre eigene Aggregatfunktion , die als Fensterfunktion verwendet werden kann.

Spezialisierte Aggregatfunktion

Es ist einfacher als man denkt:

CREATE OR REPLACE FUNCTION f_sum_cap50 (numeric, numeric)
  RETURNS numeric LANGUAGE sql AS
'SELECT CASE WHEN $1 > 50 THEN 0 ELSE $1 END + $2';

CREATE AGGREGATE sum_cap50 (numeric) (
  sfunc    = f_sum_cap50
, stype    = numeric
, initcond = 0
);

Dann:

SELECT *, sum_cap50(val) OVER (PARTITION BY fk
                               ORDER BY created) > 50 AS threshold_met 
FROM   test
WHERE  fk = 5;

Ergebnis genau wie gewünscht.

db<>fiddle hier
Altes sqlfiddle

Generische Aggregatfunktion

Damit es für alle Schwellenwerte funktioniert und beliebiger (numerischer) Datentyp , und auch NULL zulassen Werte :

CREATE OR REPLACE FUNCTION f_sum_cap (anyelement, anyelement, anyelement)
  RETURNS anyelement
  LANGUAGE sql STRICT AS
$$SELECT CASE WHEN $1 > $3 THEN '0' ELSE $1 END + $2;$$;

CREATE AGGREGATE sum_cap (anyelement, anyelement) (
  sfunc    = f_sum_cap
, stype    = anyelement
, initcond = '0'
);

Um dann mit einem Limit von, sagen wir, 110 mit einem beliebigen numerischen Typ anzurufen:

SELECT *
     , sum_cap(val, '110') OVER (PARTITION BY fk
                                 ORDER BY created) AS capped_at_110
     , sum_cap(val, '110') OVER (PARTITION BY fk
                                 ORDER BY created) > 110 AS threshold_met 
FROM   test
WHERE  fk = 5;

db<>fiddle hier
Altes sqlfiddle

Erklärung

In Ihrem Fall müssen wir uns nicht gegen NULL wehren Werte seit val ist NOT NULL definiert . Wenn NULL beteiligt sein können, definieren Sie f_sum_cap() als STRICT und es funktioniert, weil (pro Dokumentation ):

Sowohl die Funktion als auch das Aggregat benötigen ein weiteres Argument. Für das polymorphe Variante kann es sich um einen hartcodierten Datentyp oder denselben polymorphen Typ wie die führenden Argumente handeln.

Über polymorphe Funktionen:

Beachten Sie die Verwendung von nicht typisierten Zeichenfolgenliteralen , keine numerischen Literale, die standardmäßig integer wären !