我想为postgresql表设置一个触发器函数,该表应该使用从另一列派生的数据更新列。
表:
CREATE TABLE day (
symbol varchar(20) REFERENCES another_table(symbol),
date date,
open NUMERIC(8,2),
high NUMERIC(8,2),
low NUMERIC(8,2),
close NUMERIC(8,2),
sma8 NUMERIC(8,2),
PRIMARY KEY(symbol, date));
注意:复合主键。
示例INSERT:
INSERT INTO day VALUES('ABC', '2019-03-19', 102.3, 110.0, 125.3, 120.4, 0);
INSERT INTO day VALUES('ABC', '2019-03-20', 112.3, 109.0, 119.3, 118.4, 0);
INSERT INTO day VALUES('DEF', '2019-03-19', 1112.3, 1100.0, 1155.3, 1120.4, 0);
INSERT INTO day VALUES('DEF', '2019-03-20', 1202.3, 1180.0, 1205.3, 1190.4, 0);
等等。
当'date'列是唯一的主键并且该表仅包含与一个'符号'有关的数据时(即该表包含各个唯一日期上一个特定符号的数据),以下触发器功能正常工作。
create or replace function update_sma8() RETURNS TRIGGER AS
$$
BEGIN
UPDATE day d SET sma8 = s.simple_mov_avg
FROM
(
SELECT sec.date,AVG(sec.close)
OVER(ORDER BY sec.date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS
simple_mov_avg FROM day sec
)s where s.date = NEW.date --The newly inserted date
AND d.date = s.date;
RETURN NULL;
END $$ language plpgsql;
参考:SQL trigger function to UPDATE daily moving average upon INSERT
我想更新'sma8'列,其值是通过平均当前'close'值和一个特定符号的最后7'close'值得出的值('date'变化,即过去的数据)。同样适用于其他符号。
请指导我。谢谢。
您需要知道如何按“符号”过滤行。
WHERE sec.symbol = NEW.symbol
CREATE TRIGGER day_insert
AFTER INSERT ON day
FOR EACH ROW
EXECUTE PROCEDURE update_sma8();
这是完整的代码。
DROP FUNCTION public.update_sma8();
CREATE FUNCTION public.update_sma8()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
UPDATE day d SET sma8 = s.simple_mov_avg
FROM
(
SELECT sec.date,AVG(sec.close)
OVER(ORDER BY sec.date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS
simple_mov_avg FROM day sec WHERE symbol = NEW.symbol
)s where s.date = NEW.date --The newly inserted date
AND d.date = s.date ;
RETURN NULL;
END $BODY$;
ALTER FUNCTION public.update_sma8()
OWNER TO postgres;
您可以添加PARTITION BY symbol
,然后在where
子句中使用它来计算每个符号。
create or replace function update_sma8() RETURNS TRIGGER AS
$$
BEGIN
UPDATE day d SET sma8 = s.simple_mov_avg
FROM
(
SELECT sec.date,sec.symbol,AVG(sec.close)
OVER( partition by symbol ORDER BY sec.date ROWS BETWEEN
7 PRECEDING AND CURRENT ROW) AS
simple_mov_avg FROM day sec
)s where s.date = NEW.date --The newly inserted date
AND d.date = s.date
AND d.symbol = s.symbol;
RETURN NULL;
END $$ language plpgsql;