有没有办法每次计算每行数据时更新2个值?

问题描述 投票:0回答:1

我有下表:

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 个查询,但我不记得我是如何到达那里的)

sql database postgresql database-administration postgresql-11
1个回答
0
投票

您可以使用窗口函数来获取起始余额,然后相应地更新表格。

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 表。 它将起始余额计算为前一天的最终余额。 然后将最终余额作为起始余额加上每日余额,并使用这些计算值更新表格。

© www.soinside.com 2019 - 2024. All rights reserved.