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

SQL按值变化分组:连续相同值的最小时间及时长统计问题

解决连续相同值的时间序列分组统计问题

这是个很常见的连续相同值分组统计场景,你用LEAD()没成功是因为它只能单条获取下一行数据,没法把连续的相同值归为同一个逻辑组。下面给你两种通用方案,适配绝大多数主流SQL数据库:

方法一:用窗口函数实现(推荐,适用于支持窗口函数的数据库:MySQL 8.0+、PostgreSQL、SQL Server等)

核心思路是给每一组连续相同的value分配一个唯一分组ID,再基于分组ID做聚合计算:

SELECT 
    value,
    MIN(timestamp) AS min_timestamp,
    -- 计算持续时长(分钟差,和你期望的结果一致)
    TIMESTAMPDIFF(MINUTE, MIN(timestamp), MAX(timestamp)) AS duration
FROM (
    SELECT 
        value,
        timestamp,
        -- 全局行号 - 按value分组的行号 = 连续相同值的分组ID
        ROW_NUMBER() OVER (ORDER BY timestamp) 
        - ROW_NUMBER() OVER (PARTITION BY value ORDER BY timestamp) AS group_id
    FROM your_table_name -- 替换成你的实际表名
) t
GROUP BY value, group_id
ORDER BY min_timestamp;

逻辑说明:

内层查询里的group_id会自动把连续相同的value分到同一组——因为连续相同值的全局行号和分组行号的差值是固定的。外层聚合后,就能得到每个连续组的最早时间,以及该值持续的分钟数(和你给出的期望结果完全匹配)。

如果你的duration指的是「连续记录数-1」(比如3条0对应duration=2),也可以把duration改成COUNT(*) - 1,结果数值是一样的。

方法二:用变量实现(适用于不支持窗口函数的旧版MySQL)

如果你的数据库版本较低(比如MySQL 5.x),可以用用户变量来生成分组ID:

SELECT 
    value,
    MIN(timestamp) AS min_timestamp,
    TIMESTAMPDIFF(MINUTE, MIN(timestamp), MAX(timestamp)) AS duration
FROM (
    SELECT 
        value,
        timestamp,
        -- 当当前value和上一行相同时,分组ID不变;否则分组ID+1
        @group_id := IF(@prev_value = value, @group_id, @group_id + 1) AS group_id,
        @prev_value := value -- 更新上一行value的变量
    FROM your_table_name, -- 替换成你的实际表名
         (SELECT @prev_value := NULL, @group_id := 0) vars -- 初始化变量
    ORDER BY timestamp -- 必须按时间排序,保证连续判断正确
) t
GROUP BY value, group_id
ORDER BY min_timestamp;

验证结果

运行以上任意一种SQL,都会得到你想要的输出:

valuemin_timestampduration
02018-03-21 14:32:24.4172
42018-03-21 14:35:24.4171
02018-03-21 14:37:24.4171

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:58:21