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

SQL分组时如何按时间序列拆分同值连续子组获取各子组首条记录

解决方案

这是典型的序列孤岛问题,可通过新增辅助分组列实现需求,核心逻辑是为每一段连续的相同A、B记录生成唯一的组标识,再按组标识+A、B分组取最小日期即可。

方案1:双窗口函数差值法(通用性最强)

实现逻辑

  1. 按C字段升序为所有记录生成全局连续行号rn_all
  2. 按A、B字段分组,组内按C升序生成组内行号rn_ab
  3. 生成辅助列group_id = rn_all - rn_ab:连续的相同A、B记录的group_id值固定,一旦中间插入其他A、B记录,后续相同A、B的group_id会发生变化,以此区分不连续的同值分段
  4. 按A、B、group_id分组,取每组C的最小值即为目标结果

参考SQL(支持窗口函数的SQL引擎均可运行,如MySQL8.0+、Spark SQL、Hive、PostgreSQL等)

WITH t1 AS (
    -- 生成两个行号
    SELECT 
        A,
        B,
        C,
        ROW_NUMBER() OVER(ORDER BY C) AS rn_all,
        ROW_NUMBER() OVER(PARTITION BY A, B ORDER BY C) AS rn_ab
    FROM 你的表名
),
t2 AS (
    -- 生成组标识
    SELECT 
        A,
        B,
        C,
        rn_all - rn_ab AS group_id
    FROM t1
)
-- 分组取最小日期
SELECT A, B, MIN(C) AS C
FROM t2
GROUP BY A, B, group_id
ORDER BY C;

方案2:lag标记累加法

实现逻辑

  1. 用LAG窗口函数取上一行的A、B值,和当前行对比,若不同则标记为1,相同标记为0
  2. 对标记值按C升序累加,得到的累加值就是连续段的唯一组标识
  3. 按组标识分组取最小C即可

参考SQL

WITH t1 AS (
    SELECT 
        A,
        B,
        C,
        -- 判断当前行和上一行是否为相同A、B
        CASE WHEN LAG(A, 1, -1) OVER(ORDER BY C) = A AND LAG(B, 1, '') OVER(ORDER BY C) = B THEN 0 ELSE 1 END AS flag
    FROM 你的表名
),
t2 AS (
    -- 累加标记得到组ID
    SELECT 
        A,
        B,
        C,
        SUM(flag) OVER(ORDER BY C ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS group_id
    FROM t1
)
SELECT A, B, MIN(C) AS C
FROM t2
GROUP BY group_id, A, B
ORDER BY C;

两种方案均可得到你给出的期望输出结果,第一种方案逻辑更简洁不易出错,推荐优先使用。


内容的提问来源于stack exchange,提问作者Arthur Clerc-Gherardi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:54:04