उपयोगकर्ता-निर्धारित समुच्चय का उपयोग करें
लाइव परीक्षण:http://sqlfiddle.com/#!17/03ee7/1
डीडीएल
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)
;
उपयोगकर्ता-निर्धारित समुच्चय
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
पहला पैरामीटर (_accumulated_b) कॉलम का संचित मान रखता है। दूसरा पैरामीटर (_current_b) वर्तमान पंक्ति के कॉलम का मान रखता है।
आउटपुट:
आपके छद्म कोड के लिए B3 = A3 + MIN(0, B2)
मैंने इस विशिष्ट कोड का उपयोग किया:
select case when _accumulated_b < 0 then
_accumulated_b + _current_b
else
_current_b
end
इसे पोस्टग्रेज में मुहावरेदार तरीके से लिखा जा सकता है:
select _current_b + least(_accumulated_b, 0)
लाइव परीक्षण: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';
आप संचायक फ़ंक्शन के साथ अन्य भाषा का भी उपयोग कर सकते हैं, उदाहरण के लिए, plpgsql। ध्यान दें कि plpgsql (या शायद $$ उद्धरण) http://sqlfiddle.com में समर्थित नहीं है। . तो कोई लाइव टेस्ट लिंक नहीं, हालांकि यह आपकी मशीन पर काम करेगा:
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';
अपडेट करें
मैं partition by
से चूक गया , यहां एक उदाहरण डेटा है (11 से -11 में बदला गया) जहां बिना partition by
. के और partition by
. के साथ अलग परिणाम देगा:
लाइव परीक्षण: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)
;
आउटपुट:
| 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 |