我有下表:
CREATE TABLE IF NOT EXISTS import.dre
(
idmov integer,
companynumber integer,
idproduct integer,
dtdate date,
nrtank integer,
dailybalance numeric,
startbalance numeric,
endbalance numeric
)
填充以下查询(仅前 10 行):
INSERT INTO import.dre values
(1, 104, 10, '30/09/2023', 5, 0, NULL, 7600),
(2, 104, 10, '01/10/2023', 5,-1089.42, NULL, NULL),
(3, 104, 10, '02/10/2023', 5,-404.62, NULL, NULL),
(4, 104, 10, '03/10/2023', 5,-470.57, NULL, NULL),
(5, 104, 10, '04/10/2023', 5,-604.97, NULL, NULL),
(6, 104, 10, '05/10/2023', 5,10381.23, NULL, NULL),
(7, 104, 10, '06/10/2023', 5,-593.54, NULL, NULL),
(8, 104, 10, '07/10/2023', 5,-713.27, NULL, NULL),
(9, 104, 10, '08/10/2023', 5,-995.01, NULL, NULL),
(10, 104, 10, '09/10/2023', 5,-736.25, NULL, NULL)
我的任务是按照以下模式更新此表: 第一:startbalance 必须从最后一天开始合并(endbalance,0),按公司编号、idproduct、nrtank 分组。因此,使用这 10 条线,在 01/10/2023 天,起始余额应为 7600 等等。
第二:最终余额必须是当天的开始余额加上每日余额。因此,在这 10 行中,2023 年 10 月 1 日的期末余额应为 7600 + (- 1089.42),依此类推。
最终结果必须如下所示(如果这看起来不是您今天看到的最漂亮的数据集,请原谅我):
Select * from import.dre:
1, 104, 10, '30/09/2023', 5, 0, NULL, 7600
2, 104, 10, '01/10/2023', 5,-1089.42, 7600, 6510,58 -- 7600-1089.42
3, 104, 10, '02/10/2023', 5,-404.62, 6510,58, 6105,96 -- 6510.58-404.62
4, 104, 10, '03/10/2023', 5,-470.57, 6105.96, 5635,39
5, 104, 10, '04/10/2023', 5,-604.97, 5635,39, 5030,42
6, 104, 10, '05/10/2023', 5,10381.23, 5030,42, 15411,65
7, 104, 10, '06/10/2023', 5,-593.54, 15411,65, 14818,11
8, 104, 10, '07/10/2023', 5,-713.27, 14818,11, 14104,84
9, 104, 10, '08/10/2023', 5,-995.01, 14104,84, 13109,83
10, 104, 10, '09/10/2023', 5,-736.25, 13109,83, 12373,58
有什么方法可以实现这一点吗?我正在尝试(很糟糕,我知道)使用 for 循环来更新 import.dre 但我一无所获。如果有比 for 循环更好的方法,我很感激。我不知道 import.dre 能有多大。
我尝试了很多代码,但它们都更新了整个表(而不是计算每一行)。我创建的最后一个调试函数如下:
create or replace function teste()
returns void
language plpgsql
as
$$
declare
line record;
v_companynumber int;
v_idproduct int;
v_nrtank int;
v_dtdate date;
v_startbalance numeric;
v_endbalance numeric;
begin
for line in
select
*
from
import.dre
order by
companynumber, idproduct, nrtank desc, dtdate
loop
v_companynumber := line.companynumber;
v_idproduct := line.idproduct;
v_nrtank := line.nrtank;
v_dtdate := line.dtdate;
v_startbalance := lag(coalesce(line.endbalance,0), 1) over (
partition by line.companynumber, line.idproduct, line.nrtank order by line.dtdate);
v_endbalance := line.endbalance;
update import.dre
set startbalance = v_startbalance, endbalance = v_endbalance
where
companynumber = v_companynumber
and idproduct = v_idproduct
and nrtank = v_nrtank
and dtdate = v_dtdate;
end loop;
end;
最后一个查询在 startbalance 时没有分配任何内容。尝试了其他的,但这里有很多查询(最好的一个是我每天在 5 号坦克上放置 7600 个查询,但我不记得我是如何到达那里的)
您可以使用窗口函数来获取起始余额,然后相应地更新表格。
UPDATE import.dre AS d
SET
startbalance = COALESCE(prev_endbalance, 0),
endbalance = COALESCE(prev_endbalance, 0) + dailybalance
FROM (
SELECT
idmov,
LAG(endbalance) OVER (PARTITION BY companynumber, idproduct, nrtank ORDER BY dtdate) AS prev_endbalance
FROM
import.dre
) AS prev
WHERE
d.idmov = prev.idmov;
这会直接更新 import.dre 表。 它将起始余额计算为前一天的最终余额。 然后将最终余额作为起始余额加上每日余额,并使用这些计算值更新表格。