PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zbiorcze dodawanie z dynamiczną bazą w Postgres

Utwórz własną funkcję agregującą , która może być używana jako funkcja okna.

Specjalistyczna funkcja agregująca

To prostsze niż mogłoby się wydawać:

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

Następnie:

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

Wynik dokładnie taki, jak zażądano.

db<>fiddle tutaj
Stary sqlfiddle

Ogólna funkcja agregująca

Aby działało dla dowolnych progów i dowolny (numeryczny) typ danych , a także zezwalaj na NULL wartości :

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

Następnie, aby zadzwonić z limitem, powiedzmy 110, z dowolnym typem liczbowym:

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 tutaj
Stary sqlfiddle

Wyjaśnienie

W Twoim przypadku nie musimy się bronić przed NULL wartości od val jest zdefiniowany NOT NULL . Jeśli NULL może być zaangażowany, zdefiniuj f_sum_cap() jako STRICT i działa, ponieważ (zgodnie z dokumentacją ):

Zarówno funkcja, jak i agregacja przyjmują jeszcze jeden argument. Dla polimorficzny wariant może to być typ danych zakodowany na stałe lub ten sam typ polimorficzny, co główne argumenty.

O funkcjach polimorficznych:

Zwróć uwagę na użycie niewpisanych literałów ciągu , a nie literały numeryczne, które domyślnie byłyby integer !




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres nie może połączyć się z serwerem na gnieździe domeny Unix 5432

  2. Django ładuje się bardzo wolno

  3. Konwertuj tekst na Varchar

  4. Jak działa Width_Bucket() w PostgreSQL

  5. Użycie hibernacji z dużą ilością wątków