PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách truy vấn tổng hàng trước của cùng một cột với pgSql

Sử dụng tổng hợp do người dùng xác định

Kiểm tra trực tiếp: 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)
;

Tổng hợp do người dùng xác định

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

Tham số đầu tiên (_accumulated_b) giữ giá trị tích lũy của cột. Tham số thứ hai (_current_b) giữ giá trị của cột của hàng hiện tại.

Đầu ra:

Đối với mã giả của bạn B3 = A3 + MIN(0, B2)

Tôi đã sử dụng mã điển hình này:

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

Điều đó có thể được viết thành ngữ trong Postgres là:

select _current_b + least(_accumulated_b, 0)

Kiểm tra trực tiếp: 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';

Bạn cũng có thể sử dụng ngôn ngữ khác với chức năng tích lũy, ví dụ:plpgsql. Lưu ý rằng plpgsql (hoặc có lẽ là dấu ngoặc kép) không được hỗ trợ trong http://sqlfiddle.com . Vì vậy, không có liên kết kiểm tra trực tiếp, điều này sẽ hoạt động trên máy của bạn:

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

CẬP NHẬT

Tôi đã bỏ lỡ phân vùng partition by , đây là dữ liệu ví dụ (đã thay đổi 11 thành -11) mà không có partition by và với phân vùng partition by sẽ mang lại các kết quả khác nhau:

Kiểm tra trực tiếp: 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)
;

Đầu ra:

| 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. Đang cố gắng thiết lập postgres trên OSX

  2. Làm thế nào để PostgreSQL thực thi ràng buộc DUY NHẤT / loại chỉ mục nào nó sử dụng?

  3. Chuyển đổi hex trong biểu diễn văn bản thành số thập phân

  4. .NET Core ghi nhật ký vào PostgreSQL DB bằng NLog

  5. Tôi có thể kích hoạt một sự kiện trên cơ sở dữ liệu kết nối trong Entity Framework Core không?