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
!