SQL触发功能可在插入时更新每日移动平均值

时间:2019-01-10 14:49:37

标签: sql postgresql triggers

我正在尝试创建一个SQL触发函数,当将数据插入表中时,该函数应该更新列。更新是基于要插入的值中显示的值。

我有下表存储股票的每日OHLC数据。

CREATE TABLE daily_ohlc (
 cdate date,
 open numeric(8,2),
 high numeric(8,2),
 low numeric(8,2),
 close numeric(8,2),
 sma8 numeric(8,2)
);

INSERT命令:

INSERT INTO daily_ohlc (cdate, open, high, low, close) 
 values ('SYMBOL', 101, 110, 95, 108);

执行此命令后,我想基于当前值“ INSERTed”和表中已有的值来更新“ sma8”列。

到目前为止,我正在使用以下SQL查询来计算每一行的值,然后使用结果使用python更新“ sma8”列。

SELECT sec.date, AVG(sec.close) 
 OVER(ORDER BY sec.date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
simple_mov_avg FROM daily_ohlc sec;

上面的查询计算最近8条记录(包括当前行)的简单移动平均值。

使用此过程,每次插入数据时,都会更新“ sma8”列中的每一行数据。我想通过使用触发器仅更新最后一行(即正在插入的行)。该怎么做?

2 个答案:

答案 0 :(得分:0)

您不能只是按照这些原则做些什么吗?

INSERT INTO daily_ohlc 
SELECT current_date, 101, 110, 95, 108, (COUNT(*)*AVG(close)+108)/(1+Count(*))
FROM daily_ohlc
WHERE cDate >= ANY (
    SELECT MIN(cdate)
    FROM (SELECT CDate, ROW_NUMBER() OVER (ORDER BY CDate DESC) as RowNum FROM daily_ohlc) a 
    WHERE RowNum <= 7
)

我很清楚,与触发器相比,它看起来可能很复杂。
但是,我试图避免您成功创建ON INSERT触发器并且接下来要处理表中的更新的情况。在同一张表中的更新触发的过程中更新表不是最好的主意。

答案 1 :(得分:0)

您可以在触发器中使用适当的联接来进行UPDATE FROM选择查询。

create or replace function update_sma8() RETURNS TRIGGER AS
$$
 BEGIN

UPDATE daily_ohlc d SET sma8 = s.simple_mov_avg 
FROM
(
 SELECT  sec.cdate,AVG(sec.close)  
   OVER(ORDER BY sec.cdate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
    simple_mov_avg FROM daily_ohlc sec
)s where s.cdate = NEW.cdate  --The newly inserted cdate
     AND d.cdate = s.cdate;   
RETURN NULL;

END $$ language plpgsql;

Demo

使用此方法的唯一警告是,如果某人删除行或更新 close列,则必须重新计算值,这将赢得现有行不会发生。只有插入的行会看到正确的重新计算值。

相反,您可以简单地创建View来在需要时从主表为所有行计算sma8列。