Функция триггера SQL для ОБНОВЛЕНИЯ дневной скользящей средней после INSERT - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь создать функцию триггера SQL, которая должна ОБНОВЛЯТЬ столбец при вставке данных в таблицу. Обновление основано на значениях, присутствующих в значениях INSERTed.

У меня есть следующая таблица для хранения ежедневных данных 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);

Когда эта команда будет выполнена, я бы хотел обновить столбец 'sma8', основываясь на том, что текущие значения вставлены и значения уже доступны в таблице.

На данный момент я использую следующий SQL-запрос для вычисления значений для каждой строки, а затем использую результат для обновления столбца 'sma8' с помощью python.

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 голосов
/ 11 января 2019

Вы можете выполнить 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;

Демо

Единственное предостережение от использования этого метода заключается в том, что если кто-то удаляет строку или обновляет close столбец, то значения должны быть пересчитаны, чего не произойдет для существующие строки. Только вставленная строка будет видеть правильное пересчитанное значение.

Вместо этого вы можете просто создать View для вычисления столбца sma8 из основной таблицы для всех строк по запросу.

0 голосов
/ 10 января 2019

Разве вы не можете просто что-то сделать в этом направлении?

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 и затем хотите обработать обновления в таблице. Обновление таблицы в процедуре, вызванной обновлением в той же таблице, - не лучшая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...