Postgres的默认值是两条记录的差值

时间:2018-12-21 09:35:19

标签: sql postgresql expression default

我有一个带有以下列的postgres表:id,text,timestamp,diff id是自动生成的,将插入文本,时间戳是默认值,并且diff应该是当前记录的时间戳与前一条记录的时间戳(以id开头)之间的差(如果前一天与实际日期相同),如果不是,则应为0。因此,在插入文本时会自动生成所有列。 您是否知道通过表达式等将此diff设置为默认值的任何方法?我是sql的新手。

谢谢。

2 个答案:

答案 0 :(得分:2)

为此,您可以使用触发器:

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();
  1. 创建表格。 ts将当前时间戳记(now())作为默认时间戳。
  2. diff将用作秒数差异。因为可以在一秒钟内完成两次插入,所以float类型很有帮助。另一种方法可能是类型interval,它是时间戳减去的默认类型(请参见第5点)
  3. 触发器需要一个触发器函数来知道事件被触发后的操作。在此函数中,我们获取之前存储在ts中的最后一个tbl。如果不存在任何行,则借助ts
  4. 获取当前的NEWCOALESCE是要插入的当前行)
  5. 然后检查最后一个ts和当前date是否具有相同的日期(通过将两个时间戳都转换为interval进行检查)。
  6. 如果是,则计算得出类型为interval的差。要从EXTRACT(EPOCH FROM ...)中获取秒数,请使用ON BEFORE INSERT
  7. 创建触发器:在保留新行(NEW.diff)之前,执行触发器功能并设置SELECT ts, EXTRACT(EPOCH FROM ts - lag(ts) OVER (ORDER BY ts)) as diff FROM tbl; 列。

通知:

您几乎不保留以后可以计算的数据。可以借助LAG window function来计算两个时间戳之间的时差,该时间戳会将上一行的值取为当前行的值(demo):

groupingBy

如果必须删除一行,则可以看出硬存储差异的缺点。由于缺少参考,下一个的diff现在具有错误的值。您的数据可能会不一致。

答案 1 :(得分:1)

我会去VIEW

CREATE OR REPLACE VIEW v_tbl AS
SELECT id,
       txt,
       tstamp,
       coalesce (  extract ( epoch FROM tstamp - LAG(tstamp)
        OVER(PARTITION BY date_trunc('day',tstamp) ORDER BY id)),0)
 FROM tbl;

Demo