Créer votre propre fonction d'agrégation , qui peut être utilisé comme fonction de fenêtre.
Fonction d'agrégation spécialisée
C'est plus simple qu'on ne le pense :
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
);
Ensuite :
SELECT *, sum_cap50(val) OVER (PARTITION BY fk
ORDER BY created) > 50 AS threshold_met
FROM test
WHERE fk = 5;
Résultat exactement comme demandé.
db<>violon ici
Ancien sqlfiddle
Fonction d'agrégation générique
Pour que cela fonctionne pour tous les seuils et tout type de données (numérique) , et aussi autoriser NULL
valeurs :
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'
);
Ensuite, pour appeler avec une limite de, disons, 110 avec n'importe quel type numérique :
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<>violon ici
Ancien sqlfiddle
Explication
Dans votre cas, nous n'avons pas à nous défendre contre NULL
valeurs depuis val
est défini NOT NULL
. Si NULL
peut être impliqué, définissez f_sum_cap()
comme STRICT
et cela fonctionne parce que (par documentation
):
La fonction et l'agrégat prennent tous deux un argument de plus. Pour le polymorphe variante, il peut s'agir d'un type de données codé en dur ou du même type polymorphe que les arguments principaux.
À propos des fonctions polymorphes :
Notez l'utilisation de littéraux de chaîne non typés , et non des littéraux numériques, qui seraient par défaut integer
!