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.
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;
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
!