Създайте своя собствена агрегатна функция , която може да се използва като функция за прозорец.
Специализирана агрегатна функция
По-лесно е, отколкото си мислите:
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
);
След това:
SELECT *, sum_cap50(val) OVER (PARTITION BY fk
ORDER BY created) > 50 AS threshold_met
FROM test
WHERE fk = 5;
Резултат точно както е заявено.
Обща агрегатна функция
За да работи за всякакви прагове и всеки (числов) тип данни , както и разрешаване на NULL
ценностите :
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'
);
След това, за да извикате с лимит от, да речем, 110 с произволен цифров тип:
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;
Обяснение
Във вашия случай не трябва да се защитаваме срещу NULL
стойности от val
е дефинирано NOT NULL
. Ако NULL
могат да бъдат включени, дефинирайте f_sum_cap()
като STRICT
и работи, защото (по документация
):
И функцията, и агрегатът приемат още един аргумент. За полиморфен вариант може да бъде твърдо кодиран тип данни или същият полиморфен тип като водещите аргументи.
Относно полиморфните функции:
Обърнете внимание на използването на нетипизирани низови литерали , а не числови литерали, които по подразбиране биха били integer
!