sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan forespørges sum forrige række i samme kolonne med med pgSql

Brug brugerdefineret aggregat

Live test:http://sqlfiddle.com/#!17/03ee7/1

DDL

CREATE TABLE t
    (grop varchar(1), month_year text, something int)
;

INSERT INTO t
    (grop, month_year, something)
VALUES
    ('a', '201901', -2),
    ('a', '201902', -4),
    ('a', '201903', -6),
    ('a', '201904', 60),
    ('a', '201905', -2),
    ('a', '201906', 9),
    ('a', '201907', 11),
    ('b', '201901', 100),
    ('b', '201902', -200),
    ('b', '201903', 300),
    ('b', '201904', -50),
    ('b', '201905', 30),
    ('b', '201906', -88),
    ('b', '201907', -86)
;
 

Brugerdefineret aggregat

create or replace function negative_accum(_accumulated_b numeric, _current_b numeric)
returns numeric as
$$
    select case when _accumulated_b < 0 then
        _accumulated_b + _current_b
    else
        _current_b
    end
$$ language 'sql';

create aggregate negative_summer(numeric)
(
    sfunc = negative_accum,
    stype = numeric,
    initcond = 0
);

select  
    *, 
  negative_summer(something) over (order by grop, month_year) as result
from t
 

Den første parameter (_accumulated_b) indeholder den akkumulerede værdi af kolonnen. Den anden parameter (_current_b) indeholder værdien af ​​den aktuelle rækkes kolonne.

Output:

Med hensyn til din pseudokode B3 = A3 + MIN(0, B2)

Jeg brugte denne typiske kode:

select case when _accumulated_b < 0 then
    _accumulated_b + _current_b
else
    _current_b
end
 

Det kan skrives idiomatisk i Postgres som:

select _current_b + least(_accumulated_b, 0)
 

Live test:http://sqlfiddle.com/#!17/70fa8/1

create or replace function negative_accum(_accumulated_b numeric, _current_b numeric)
returns numeric as
$$
    select _current_b + least(_accumulated_b, 0) 
$$ language 'sql';
 

Du kan også bruge andre sprog med akkumulatorfunktion, f.eks. plpgsql. Bemærk, at plpgsql (eller måske $$-citatet) ikke understøttes i http://sqlfiddle.com . Så ingen live testlink, dette ville dog fungere på din maskine:

create or replace function negative_accum(_accumulated_b numeric, _current_b numeric)
returns numeric as
$$begin
    return _current_b + least(_accumulated_b, 0);
end$$ language 'plpgsql';
 

OPDATERING

Jeg gik glip af partition by , her er et eksempel på data (ændret 11 til -11) uden partition by og med partition by ville give andre resultater:

Live test:http://sqlfiddle.com/#!17/87795/4

INSERT INTO t
    (grop, month_year, something)
VALUES
    ('a', '201901', -2),
    ('a', '201902', -4),
    ('a', '201903', -6),
    ('a', '201904', 60),
    ('a', '201905', -2),
    ('a', '201906', 9),
    ('a', '201907', -11), -- changed this from 11 to -11
    ('b', '201901', 100),
    ('b', '201902', -200),
    ('b', '201903', 300),
    ('b', '201904', -50),
    ('b', '201905', 30),
    ('b', '201906', -88),
    ('b', '201907', -86)
;
 

Output:

| grop | month_year | something | result_wrong | result | |------|------------|-----------|--------------|--------| | a | 201901 | -2 | -2 | -2 | | a | 201902 | -4 | -6 | -6 | | a | 201903 | -6 | -12 | -12 | | a | 201904 | 60 | 48 | 48 | | a | 201905 | -2 | -2 | -2 | | a | 201906 | 9 | 7 | 7 | | a | 201907 | -11 | -11 | -11 | | b | 201901 | 100 | 89 | 100 | | b | 201902 | -200 | -200 | -200 | | b | 201903 | 300 | 100 | 100 | | b | 201904 | -50 | -50 | -50 | | b | 201905 | 30 | -20 | -20 | | b | 201906 | -88 | -108 | -108 | | b | 201907 | -86 | -194 | -194 |

  1. Skal jeg bruge mysql_close(forbindelse)?

  2. mysql hamming afstand mellem to phash

  3. MySQL regexp på indekser

  4. Sådan beregnes om alderen er inden for intervallet fra fødselsåret, mens du henter fødselsåret fra Db i Django ORM