You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQLite3与PostgreSQL中用LAG函数创建存储生成列

系统监控时序数据表实现方案(PostgreSQL + SQLite3)

核心限制说明

无论是PostgreSQL的STORED生成列,还是SQLite的GENERATED ALWAYS AS ... STORED,均不支持引用其他行的数据(比如LAG()这类窗口函数)。生成列的计算仅能依赖当前行字段或常量,因此要实现基于上一行数据的自动计算,必须通过触发器完成。


PostgreSQL 实现步骤

1. 创建基础监控表

CREATE TABLE system_monitor (
    id SERIAL PRIMARY KEY,
    ts TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    cputil NUMERIC(5,2),
    memfree NUMERIC(10,2),
    util_diff NUMERIC(5,2),  -- 存储cputil与上一行的差值
    mem_diff NUMERIC(10,2),  -- 存储memfree与上一行的差值
    change TEXT              -- 存储CPU使用率变化方向(Up/Down/No Change)
);

2. 编写触发器计算函数

CREATE OR REPLACE FUNCTION calc_monitor_diffs()
RETURNS TRIGGER AS $$
BEGIN
    -- 计算cputil差值:当前值 - 上一行值
    SELECT NEW.cputil - LAG(cputil) OVER (ORDER BY ts)
    INTO NEW.util_diff
    FROM system_monitor
    ORDER BY ts DESC
    LIMIT 1;

    -- 计算memfree差值:当前值 - 上一行值
    SELECT NEW.memfree - LAG(memfree) OVER (ORDER BY ts)
    INTO NEW.mem_diff
    FROM system_monitor
    ORDER BY ts DESC
    LIMIT 1;

    -- 判断CPU使用率变化方向
    NEW.change := CASE
        WHEN NEW.util_diff > 0 THEN 'Up'
        WHEN NEW.util_diff < 0 THEN 'Down'
        ELSE 'No Change'
    END;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

3. 绑定触发器到插入事件

CREATE TRIGGER trigger_calc_monitor_diffs
BEFORE INSERT ON system_monitor
FOR EACH ROW EXECUTE FUNCTION calc_monitor_diffs();

SQLite3 实现步骤

1. 创建基础监控表

CREATE TABLE system_monitor (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ts DATETIME DEFAULT CURRENT_TIMESTAMP,
    cputil REAL,
    memfree REAL,
    util_diff REAL,
    mem_diff REAL,
    change TEXT
);

2. 创建触发器(SQLite直接内置逻辑)

CREATE TRIGGER trigger_calc_monitor_diffs
BEFORE INSERT ON system_monitor
FOR EACH ROW
BEGIN
    -- 计算cputil与上一行的差值
    SELECT NEW.cputil - cputil
    INTO NEW.util_diff
    FROM system_monitor
    ORDER BY ts DESC
    LIMIT 1;

    -- 计算memfree与上一行的差值
    SELECT NEW.memfree - memfree
    INTO NEW.mem_diff
    FROM system_monitor
    ORDER BY ts DESC
    LIMIT 1;

    -- 设置变化方向标识
    SET NEW.change = CASE
        WHEN NEW.util_diff > 0 THEN 'Up'
        WHEN NEW.util_diff < 0 THEN 'Down'
        ELSE 'No Change'
    END;
END;

边界情况处理

当插入第一行数据时,util_diff和mem_diff会返回NULL,change会显示No Change。如果需要默认值(比如差值设为0),可以在触发器中添加COALESCE处理:

  • PostgreSQL示例:NEW.util_diff := COALESCE(NEW.cputil - LAG(cputil) OVER (...), 0);
  • SQLite示例:SELECT COALESCE(NEW.cputil - cputil, 0) INTO NEW.util_diff FROM ...;

内容的提问来源于stack exchange,提问作者skeetastax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 23:20:05