如何创建对列的总和进行计数并将其插入到另一个中的触发器

时间:2019-06-02 18:36:47

标签: sql postgresql

我想将一列的总和放入另一张表的列中。每个ID的所有内容。开始时,我的列为NULL,所以我想用此值更新它们。

到现在为止,我一直尝试对SUM进行计数,它当然可以工作,但是当我尝试编写更多代码时,它每次都会失败。更多。这并不是说我无法编写代码。我只是找不到使我感到“哦,我应该走那条路”的逻辑。这是我的第一个诱因,对我来说真的很难。可悲的是,关于StackOverflow的所有答案都比我自己的要难得多。

更新:刚刚发现内置了功能。有什么可以使像这样的事情成为可能吗?

DROP TABLE IF EXISTS daily;

CREATE TABLE daily (
    idd SERIAL PRIMARY KEY,
    p_id INTEGER NOT NULL,
    dailyDate DATE NOT NULL,
    dailyKcal INTEGER DEFAULT NULL,
    burnedKcal INTEGER DEFAULT NULL,
    FOREIGN KEY(p_id) REFERENCES proteges(idp)
);


DROP TABLE IF EXISTS exercises;

CREATE TABLE exercises (
    d_did INTEGER NOT NULL,
    exerciseName VARCHAR(30) NOT NULL,
    startAt TIME NOT NULL,
    endAt TIME NOT NULL,
    kcalPerHour INTEGER NOT NULL,
    FOREIGN KEY (d_did) REFERENCES daily(idd)
);

--- FAIL ---
CREATE TRIGGER update_daily_exercises 
    AFTER INSERT ON exercises
    UPDATE daily 
    SET burnedkcal = (SELECT sum(kcalperhour) FROM exercises GROUP BY d_did)
    WHERE idd = d_did

我期望什么? 假设有类似的东西:

d_did | ... | kcalperhour
1     | ... | 492
2     | ... | 321
1     | ... | 346
idd | ... | burnedkcal
1   | ... | NULL
2   | ... | NULL

在POST之后,我希望它像这样:

idd | ... | burnedkcal
1   | ... | 838
2   | ... | 321

2 个答案:

答案 0 :(得分:0)

将可以从其他值计算得出的值进行材料化是危险的,它会很快导致不一致。您应该删除存储总和的列。如果需要,请从现有值中查询它。为了方便起见,您可以创建一个视图。

ALTER TABLE daily
            DROP burnedkcal;

CREATE VIEW daily_with_burnedcal
AS
SELECT d.idd,
       d.p_id,
       d.dailydate,
       d.dailykcal,
       coalesce(sum(e.kcalperhour), 0) burnedkcal
       FROM daily d
            LEFT JOIN exercises e
                      ON e.d_did = d.idd
       GROUP BY d.idd,
                d.p_id,
                d.dailydate,
                d.dailykcal;

答案 1 :(得分:0)

万一有人有同样的问题。我什至不确定我的问题是否答案,但是我知道那就是我所做的。

CREATE OR REPLACE FUNCTION public.sum_exercises() RETURNS TRIGGER AS 
$update_daily_exercises$
DECLARE
    total INTEGER;
    r daily%rowtype;
BEGIN
    ---SELECT sum(kcalPerHour) FROM exercises JOIN daily ON idd = d_did WHERE d_did = x INTO total;---
    FOR r IN 
        SELECT * FROM daily ORDER BY idd DESC
    LOOP
    SELECT sum(kcalPerHour) FROM exercises JOIN daily ON idd = d_did WHERE d_did = r.idd INTO total;
    UPDATE daily SET burnedKcal = total WHERE idd = r.idd;
    END LOOP;
    RETURN NEW;
END;
$update_daily_exercises$ 
LANGUAGE PLPGSQL;

CREATE TRIGGER update_daily_exercises 
    AFTER INSERT ON exercises
    FOR EACH ROW 
    EXECUTE PROCEDURE sum_exercises();