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

PostgreSQL根据action列交替值合并时间生成设备OFF状态区间

纯SQL实现设备OFF状态区间合并

完全可以直接用标准SQL实现需求,不需要移植PL/pgSQL或者在服务端额外写处理逻辑,核心通过窗口函数就能一步解决连续重复动作消重、区间生成的问题,也不需要单独做重叠区间合并。

实现逻辑

核心思路是给连续相同状态的记录分配同一个分组ID,再按分组聚合取起止时间:

  • 按时间升序排列所有事件,用LAG()取每条记录的上一个动作
  • 遇到动作和上一条不一致时,判定为新状态组的起点,累计计数生成唯一分组ID,连续相同动作的记录会共享同一个分组ID
  • 按分组聚合,取组内最早时间作为区间起点,取下一个状态组的最早时间作为当前区间终点
  • 最后过滤出状态为OFF的闭合区间即可

可直接运行的SQL代码

假设事件表名为device_events,时间字段为event_time,动作字段为action:

WITH marked_events AS (
    SELECT
        event_time,
        action,
        SUM(
            -- 动作和上一条一致就不新增分组,不一致则分组号+1
            CASE WHEN LAG(action) OVER (ORDER BY event_time) = action THEN 0 ELSE 1 END
        ) OVER (ORDER BY event_time ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS group_id
    FROM device_events
),
state_ranges AS (
    SELECT
        group_id,
        action AS state,
        MIN(event_time) AS range_start,
        LEAD(MIN(event_time)) OVER (ORDER BY group_id) AS range_end
    FROM marked_events
    GROUP BY group_id, action
)
SELECT
    CONCAT(range_start, ' - ', range_end) AS range,
    state
FROM state_ranges
WHERE state = 'OFF' AND range_end IS NOT NULL;

补充说明

  • 连续重复的OFF/ON记录会自动归入同一分组,聚合时直接合并为一个区间,不需要提前做去重处理
  • 按时间顺序生成的分组天然不存在重叠区间,不需要额外做区间合并操作
  • 如果是多设备的场景,只需要在所有窗口函数的OVER子句中添加PARTITION BY 设备ID字段,即可按设备分别计算状态区间
  • 用提供的示例数据运行上述代码,输出结果和期望结果完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:57:23