sql >> Databasteknik >  >> RDS >> PostgreSQL

Kumulativ addering med dynamisk bas i Postgres

Skapa din egen aggregatfunktion , som kan användas som fönsterfunktion.

Specialiserad aggregatfunktion

Det är enklare än man kan tro:

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
);

Sedan:

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

Resultat exakt som efterfrågat.

db<>fiol här
Gammal sqlfiddle

Allmän aggregatfunktion

För att få det att fungera för alla trösklar och alla (numeriska) datatyper , och även tillåt NULL värden :

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'
);

För att sedan ringa med en gräns på till exempel 110 med valfri numerisk typ:

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<>fiol här
Gammal sqlfiddle

Förklaring

I ditt fall behöver vi inte försvara oss mot NULL värden sedan val är definierad NOT NULL . Om NULL kan vara involverade, definiera f_sum_cap() som STRICT och det fungerar eftersom (per dokumentation ):

Både funktion och aggregat tar ytterligare ett argument. För den polymorfa variant kan det vara en hårdkodad datatyp eller samma polymorfa typ som de ledande argumenten.

Om polymorfa funktioner:

Observera användningen av otypade strängliterals , inte numeriska bokstaver, som som standard skulle vara integer !




  1. Förslag för implementering av revisionstabeller i SQL Server?

  2. PyMySQL kan inte ansluta till MySQL på localhost

  3. SQL Server Temp-tabell vs Tabellvariabel

  4. Skapa ett index på en tabellvariabel