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

Jak zapytać o sumę poprzedniego wiersza tej samej kolumny za pomocą pgSql

Użyj agregatu zdefiniowanego przez użytkownika

Test na żywo: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)
;

Agregacja zdefiniowana przez użytkownika

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

Pierwszy parametr (_accumulated_b) przechowuje skumulowaną wartość kolumny. Drugi parametr (_current_b) przechowuje wartość kolumny bieżącego wiersza.

Wyjście:

Jeśli chodzi o Twój pseudokod B3 = A3 + MIN(0, B2)

Użyłem tego typowego kodu:

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

Można to napisać idiomatycznie w Postgresie jako:

select _current_b + least(_accumulated_b, 0)

Test na żywo: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';

Możesz również użyć innego języka z funkcją akumulatora, np. plpgsql. Zauważ, że plpgsql (lub cytat $$) nie jest obsługiwany w http://sqlfiddle.com . Więc nie ma linku do testu na żywo, ale działałoby to na twoim komputerze:

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

AKTUALIZUJ

Brakowało mi partition by , oto przykładowe dane (zmienione 11 na -11), gdzie bez partition by i z partition by dałoby różne wyniki:

Test na żywo: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)
;

Wyjście:

| 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy istnieje sposób na przydatne indeksowanie kolumny tekstowej zawierającej wzorce wyrażeń regularnych?

  2. Django:odmowa uprawnień podczas próby uzyskania dostępu do bazy danych po przywróceniu (migracji)

  3. Postgres zagnieżdżone zapytanie SQL do pola liczenia

  4. Podaj przygotowaną instrukcję z tablicą

  5. Uzyskaj ten sam wynik, gdy próbujesz znaleźć inne dane