我想为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 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);
以此类推。
当“日期”列是唯一的主键,并且该表仅包含与一个“符号”有关的数据时(例如,该表包含各个唯一日期的一个特定符号的数据),以下触发器功能可以正常工作。
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
我想用通过平均一个特定交易品种的当前“关闭”值和最后7个“关闭”值得出的值来更新“ sma8”列(“日期”有所不同,即过去的数据)。其他符号也是如此。
请引导我。谢谢。
答案 0 :(得分:0)
您需要知道如何通过“符号”过滤行。
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;
答案 1 :(得分:0)
您可以添加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;