我需要将RESULT列放入同一行的SOMETHING和前一行的SOMETHING列之和(如果它是负数),例如B3 = A3 + MIN(0,B2)。
我尝试使用窗口函数,但无济于事,它只是显示出它不是预期的结果。 (month_year是DATE字段)
group month_year something result
a jan/19 -2 -2
a fev/19 -4 -6
a mar/19 -6 -12
a abr/19 60 48
a mai/19 -2 46
a jun/19 9 55
a jul/19 11 66
b jan/19 100 100
b fev/19 -200 -100
b mar/19 300 200
b abr/19 -50 150
b mai/19 30 180
b jun/19 -88 92
b jul/19 -86 6
预期结果:
这是我要寻找的结果,如果还有其他方法可以实现我的全部追求。你能帮忙吗?
答案 0 :(得分:1)
实时测试: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
在Postgres中习惯上可以这样写:
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。请注意,http://sqlfiddle.com中不支持plpgsql(或者可能是$$引号)。因此,没有实时测试链接,尽管它可以在您的计算机上运行:
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 |
答案 1 :(得分:0)
您可能在使用window函数时遇到了问题,因为您需要订购一些东西,而且month_year列不会自然排序。请参见此SQL小提琴,在该列中将列替换为类似日期(可以正确排序)的内容。
http://sqlfiddle.com/#!18/7a304/1/0
CREATE TABLE t
([grop] varchar(1), [month_year] varchar(6), [something] int, [result] int)
INSERT INTO t
([grop], [month_year], [something], [result])
VALUES
('a', '201901', -2, -2),
('a', '201902', -4, -6),
('a', '201903', -6, -12),
('a', '201904', 60, 48),
('a', '201905', -2, -2),
('a', '201906', 9, 7),
('a', '201907', 11, 11),
('b', '201901', 100, 100),
('b', '201902', -200, -200),
('b', '201903', 300, 100),
('b', '201904', -50, -50),
('b', '201905', 30, -20),
('b', '201906', -88, -108),
('b', '201907', -86, -194)
select
grop, month_year, something, result,
sum(something) over (partition by grop order by grop, month_year) as rtot
from
t
| grop | month_year | something | result | rtot |
|------|------------|-----------|--------|------|
| a | 201901 | -2 | -2 | -2 |
| a | 201902 | -4 | -6 | -6 |
| a | 201903 | -6 | -12 | -12 |
| a | 201904 | 60 | 48 | 48 |
| a | 201905 | -2 | -2 | 46 |
| a | 201906 | 9 | 7 | 55 |
| a | 201907 | 11 | 11 | 66 |
| b | 201901 | 100 | 100 | 100 |
| b | 201902 | -200 | -200 | -100 |
| b | 201903 | 300 | 100 | 200 |
| b | 201904 | -50 | -50 | 150 |
| b | 201905 | 30 | -20 | 180 |
| b | 201906 | -88 | -108 | 92 |
| b | 201907 | -86 | -194 | 6 |
问题的另一部分是当您获得正数时重置运行总计。我不确定是否可以在SQL中做到这一点,而无需放入存储的proc中,但是也许有一个更清晰的例子,有经验的人会加入。