Home > Back-end >  Automatically set SUM calculation's result as column value during / after row insert
Automatically set SUM calculation's result as column value during / after row insert

Time:12-09

I have an SQL table called "credits" which contain the following columns:

  • id (Serial ID for rows (1,2,3,....))
  • account_id (ID of associated client)
  • change (int4)
  • rolling_change

Every time during/after a row insert, I'd like the result of this Query to be the "rolling_change" column's value:

SELECT SUM(change)
FROM credits
WHERE account_id = {account_id} AND id < {this_id};

How can I make this process happen automatically on every row insert?

(I'm using DBeaver for reference)

CodePudding user response:

Here's an example that updates the empty rolling_change after inserts.

CREATE TABLE credits (
    id          SERIAL PRIMARY KEY,
    account_id  INT NOT NULL,
    change      INT NOT NULL, 
    rolling_change INT
);
CREATE OR REPLACE FUNCTION calc_credits_rolling_change() 
RETURNS trigger AS $calc_rolling_change$
BEGIN
    UPDATE credits tgt
    SET rolling_change = src.rolling_change
    FROM (
        SELECT id
        , SUM(change) OVER (PARTITION BY account_id 
                            ORDER BY id) AS rolling_change
        FROM credits
    ) src
    WHERE src.id = tgt.id
      AND tgt.rolling_change IS NULL;

    RETURN NEW;
END;
$calc_rolling_change$ LANGUAGE plpgsql;
CREATE TRIGGER trg_credits_rolling_change
  AFTER INSERT
  ON credits
  EXECUTE PROCEDURE calc_credits_rolling_change();
INSERT INTO credits (account_id, change) VALUES
  (1, 1), (1, 0)
, (2, 1), (2, 1), (2, 0);

INSERT INTO credits (account_id, change) VALUES
  (3, 2), (3, 1), (1, 10)
select * from credits order by account_id, id;
id account_id change rolling_change
1 1 1 1
2 1 0 1
8 1 10 11
3 2 1 1
4 2 1 2
5 2 0 2
6 3 2 2
7 3 1 3

Demo on db<>fiddle here

  • Related