Използвайте дефиниран от потребителя агрегат
Тест на живо: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);
Дефиниран от потребителя агрегат
създайте или заменете функция negative_accum(_accumulated_b numeric, _current_b numeric)връща число като$$ изберете случай, когато _accumulated_b <0 тогава _accumulated_b + _current_b else _current_b end$$ език 'sql';създайте сборен negative_summer(numeric)( sfunc =negative_accum, stype =numeric, initcond =0); изберете *, negative_summer(нещо) над (подреждане по група, месец_година) като резултат от t
Първият параметър (_accumulated_b) съдържа натрупаната стойност на колоната. Вторият параметър (_current_b) съдържа стойността на колоната на текущия ред.
Изход:
Що се отнася до вашия псевдокод B3 =A3 + MIN(0, B2)
Използвах този типичен код:
изберете случай, когато _accumulated_b <0 след това _accumulated_b + _current_belse _current_bend
Това може да се напише идиоматично в Postgres като:
изберете _current_b + least(_accumulated_b, 0)
Тест на живо:http://sqlfiddle.com/#!17/70fa8/1
създаване или замяна на функция negative_accum(_accumulated_b numeric, _current_b numeric)връща число като$$ select _current_b + least(_accumulated_b, 0) $$ език 'sql';
Можете също да използвате друг език с акумулираща функция, например plpgsql. Обърнете внимание, че plpgsql (или може би цитатът $$) не се поддържа в http://sqlfiddle.com . Така че няма тестова връзка на живо, но това ще работи на вашата машина:
създайте или заменете функция negative_accum(_accumulated_b numeric, _current_b numeric)връща число as$$begin return _current_b + least(_accumulated_b, 0);end$$ език 'plpgsql';
АКТУАЛИЗАЦИЯ
Пропуснах дяла от
, ето примерни данни (променени 11 на -11), където без разделяне по
и с разделяне по
ще доведе до различни резултати:
Тест на живо: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), -- промени това от 11 на -11 ('b', '201901', 100), ('b', '201902', -200), ('b', '201903', 300 ), ('b', '201904', -50), ('b', '201905', 30), ('b', '201906', -88), ('b', '201907', - 86);
Изход:
<предварителен код>| хващам | месец_година | нещо | резултат_грешен | резултат ||------|------------|-----------|--------------| --------|| 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 || б | 201901 | 100 | 89 | 100 || б | 201902 | -200 | -200 | -200 || б | 201903 | 300 | 100 | 100 || б | 201904 | -50 | -50 | -50 || б | 201905 | 30 | -20 | -20 || б | 201906 | -88 | -108 | -108 || б | 201907 | -86 | -194 | -194 |