sql - 在 PostgreSQL 中插入后计算平均值

标签 sql postgresql function triggers

我试图获取过去 24 小时内传感器引入的所有值的字段 pm10_ug_m3 的平均值,但使用我当前的代码,平均值不包括插入行的值。

目前,由于触发器是在插入之前完成的,因此没有考虑在字段 pm10_ug_m3 中插入​​的最后一个值。因此,该领域引入的平均值是 3,而不是从 (10+3)/2 获得的 6.5

1)创建表格并添加一些日期:

(
  ID bigint NOT NULL,
  SensorID character(10),
  pm10_ug_m3 numeric(10,2),
  tense timestamp without time zone,
  average float,
  CONSTRAINT id_pk PRIMARY KEY (ID)
);

INSERT INTO sensor (ID,SensorID,pm10_ug_m3,tense) VALUES
(1,'S16',1,'2019-07-10 04:25:59'),
(2,'S20',3,'2017-07-10 02:25:59');

2) 创建触发器来计算同一传感器过去 24 小时内捕获的记录的 pm10_ug_m3 平均值:

CREATE OR REPLACE FUNCTION calculate_avg() RETURNS TRIGGER AS $BODY$
  BEGIN
  NEW.average := ( SELECT AVG(pm10_ug_m3)
                        FROM sensor
                        WHERE SensorID=NEW.SensorID 
                        AND tense>= NEW.tense - INTERVAL '24 HOURS');

  RETURN NEW;
  END;
  $BODY$
 LANGUAGE plpgsql;


CREATE TRIGGER calculate_avg_trigger BEFORE INSERT OR UPDATE 
    ON sensor FOR EACH ROW 
    EXECUTE PROCEDURE calculate_avg();

3)插入一个新行,其中将填充字段平均值:

INSERT INTO sensor (ID,SensorID,pm10_ug_m3,tense) VALUES
(3,'S20',10,'2017-07-10 04:25:59')

最佳答案

这不起作用,因为 AVG() 函数仅考虑仍然插入的数据,而不考虑将要插入的新数据

将触发点从 BEFORE 更改为 AFTER 确实会提供正确的结果,但不会设置它,因为 INSERT 已经有至此已经完成。

因此,实现结果的一种方法是在触发函数中手动计算平均值:

SELECT (SUM(pm10_ug_M3) + NEW.pm10_ug_m3) / (COUNT(pm10_ug_m3) + 1)
FROM ...

SUM() 当前值 + 新值除以 COUNT() 当前值 + 新值。

demo:db<>fiddle

关于sql - 在 PostgreSQL 中插入后计算平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56970433/

相关文章:

mysql - CASE 语句以及如何使用其中的值

postgresql - 如何在postgres中返回中位数和x标准差的值

sql - plpgsql 函数。如何将值与一组值进行比较?

list - Dart ListBase 中的不一致

c - 使用 stat() 函数测试 DIRENT 是目录还是文件的正确方法是什么?

mysql - 为什么我的 JOIN 显示双重结果?

mysql - 提供每年/每月新客户与回头客的数量

mysql - 如何在mysql的删除/更新查询中使用子查询

javascript - 当我尝试在 Heroku 上使用 POSTGRESQL 更新数据库时,出现 22001 错误

c++ - 函数计算被跳过的字符串类的字符?