Для этого вы можете использовать триггер:
demo: db <> fiddle
CREATE TABLE tbl (
id int,
ts timestamp DEFAULT now(), -- 1
diff float -- 2
);
CREATE FUNCTION set_ts_diff() RETURNS trigger AS $$
DECLARE
_last_ts timestamp;
BEGIN
SELECT COALESCE(MAX(ts), NEW.ts) FROM tbl INTO _last_ts; -- 3
IF (NEW.ts::date = _last_ts::date) THEN -- 4
NEW.diff := EXTRACT(EPOCH FROM NEW.ts - _last_ts); -- 5
ELSE
NEW.diff := 0;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr_set_ts_diff BEFORE INSERT ON tbl -- 6
FOR EACH ROW EXECUTE PROCEDURE set_ts_diff();
- Создайте свою таблицу.
ts
получает текущую метку времени (now()
) по умолчанию. diff
будет использоваться как разница в секундах.Поскольку две вставки могут быть сделаны за одну секунду, помогает тип float
.Другим способом может быть тип interval
, который является типом по умолчанию для вычитаний меток времени (см. Пункт 5) - Для триггера требуется функция триггера, чтобы знать, что делать после запуска события.В этой функции мы получаем последний
ts
, сохраненный в tbl
ранее.Если строки не существует, берется текущий ts
(NEW
- текущая строка для вставки) с помощью COALESCE
- Затем проверьте, совпадают ли последний и текущий
ts
дата (проверяется путем приведения обеих меток времени к date
). - Если это так, вычислите разницу, которая приводит к типу
interval
.Чтобы получить секунды из interval
, используйте EXTRACT(EPOCH FROM ...)
. - Создайте триггер: перед сохранением новой строки (
ON BEFORE INSERT
) выполните функцию триггера и установите столбец NEW.diff
.
Примечание:
Вам едва следует сохранять данные, которые можно рассчитать позже.Разницу между двумя временными метками можно рассчитать с помощью оконной функции LAG
, которая переводит значение предыдущей строки в текущую ( demo ):
SELECT
ts,
EXTRACT(EPOCH FROM ts - lag(ts) OVER (ORDER BY ts)) as diff
FROM
tbl;
Недостаток жесткого сохранения разницы можно увидеть, если вам нужно удалить одну строку.Различие следующего теперь имеет неправильное значение, потому что его ссылка отсутствует.Ваши данные могут стать противоречивыми.