sql >> Databáze >  >> RDS >> PostgreSQL

Kumulativní přidávání s dynamickým základem v Postgresu

Vytvořte si vlastní agregační funkci , kterou lze použít jako funkci okna.

Specializovaná agregační funkce

Je to jednodušší, než by se mohlo zdát:

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

Potom:

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

Výsledek přesně podle požadavků.

db<>fiddle zde
Staré sqlfiddle

Obecná agregační funkce

Aby to fungovalo pro jakékoli prahové hodnoty a jakýkoli (číselný) datový typ a také povolit NULL hodnoty :

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

Potom, chcete-li volat s limitem, řekněme, 110 s libovolným číselným typem:

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 zde
Staré sqlfiddle

Vysvětlení

Ve vašem případě se nemusíme bránit NULL hodnoty od val je definováno NOT NULL . Pokud NULL může být zapojeno, definujte f_sum_cap() jako STRICT a funguje to, protože (podle dokumentace ):

Funkce i agregace mají ještě jeden argument. Pro polymorfní varianta může být pevně zakódovaný datový typ nebo stejný polymorfní typ jako hlavní argumenty.

O polymorfních funkcích:

Všimněte si použití netypizovaných řetězcových literálů , nikoli číselné literály, které by ve výchozím nastavení měly hodnotu integer !




  1. pomocí kopie v postgresql?

  2. CHYBA:funkce dblink(neznámé, neznámé) neexistuje

  3. Transakce v MySQL - Nelze vrátit zpět

  4. Zastaralé funkce, které je třeba vyjmout ze sady nástrojů – část 2