PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Cara menanyakan jumlah baris sebelumnya dari kolom yang sama dengan pgSql

Gunakan agregat yang ditentukan pengguna

Tes langsung: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)
;

Agregat yang ditentukan pengguna

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

Parameter pertama (_accumulated_b) menyimpan nilai akumulasi kolom. Parameter kedua (_current_b) menyimpan nilai kolom baris saat ini.

Keluaran:

Adapun kode semu Anda B3 = A3 + MIN(0, B2)

Saya menggunakan kode tipikal ini:

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

Itu dapat ditulis secara idiomatis di Postgres sebagai:

select _current_b + least(_accumulated_b, 0)

Tes langsung: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';

Anda juga dapat menggunakan bahasa lain dengan fungsi akumulator, mis., plpgsql. Perhatikan bahwa plpgsql (atau mungkin kutipan $$) tidak didukung di http://sqlfiddle.com . Jadi tidak ada tautan uji langsung, ini akan berfungsi di mesin Anda:

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

PERBARUI

Saya melewatkan partition by , ini contoh datanya (diubah 11 menjadi -11) dimana tanpa partition by dan dengan partition by akan menghasilkan hasil yang berbeda:

Tes langsung: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)
;

Keluaran:

| 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. Apa urutan default dari daftar yang dikembalikan dari panggilan filter Django?

  2. konversi nilai kolom jsonb ke beberapa kolom di PostgreSQL

  3. Memetakan bidang titik geometri PostGIS dengan Hibernate pada Spring Boot

  4. Manfaat PostgreSQL

  5. Bagaimana cara membuat fungsi pemicu secara dinamis di pgsql?