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

SQL Server:满足指定条件前为连续行分配相同行号

在SQL Server中为连续行分配相同分组ID直至触发条件

嘿,这个需求在SQL Server里其实很好解决,核心思路是用窗口函数+累计求和的组合来给连续行打上分组标记,直到触发你设定的条件为止。我就拿你提供的数据集来一步步说明:

首先,先把你的数据集用SQL表的形式呈现出来(方便测试):

CREATE TABLE YourTable (
    ukey INT,
    id INT,
    code INT,
    create_date DATETIME2
);

INSERT INTO YourTable VALUES
(1, 1082, 9053, '2018-03-01 23:18:51.0000000'),
(2, 1082, 9035, '2018-03-01 23:19:21.0000000'),
(3, 1082, 9053, '2018-03-01 23:22:55.0000000'),
(4, 1082, 9535, '2018-03-01 23:23:30.0000000'),
(5, 1196, 3145, '2018-03-05 07:27:15.0000000'),
(6, 1196, 3162, '2018-03-05 07:27:50.0000000'),
(7, 1196, 3175, '2018-03-05 07:28:24.0000000'),
(8, 1196, 3235, '2018-03-05 07:28:57.0000000'),
(9, 1196, 3295, '2018-03-05 07:29:31.0000000'),
(10, 1196, 3448, '2018-03-05 07:30:04.0000000'),
(11, 1196, 3465, '2018-03-05 07:30:37.0000000');

解法1:当特定code出现时开启新分组

假设你的“触发条件”是当code等于9053时,开启一个新的分组(从你的数据看,id=1082的行里两次出现9053,很像是分组的起点),可以用下面的查询:

SELECT 
    ukey,
    id,
    code,
    create_date,
    -- 生成分组ID:每次遇到code=9053就加1,后续行继承当前分组ID
    SUM(CASE WHEN code = 9053 THEN 1 ELSE 0 END) OVER (
        PARTITION BY id 
        ORDER BY create_date 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS group_id
FROM YourTable
ORDER BY id, create_date;

逻辑解释:

  • PARTITION BY id:先按id拆分数据集,确保不同id的分组完全独立,不会混在一起
  • ORDER BY create_date:保证行是按时间顺序处理的,符合“连续行”的要求
  • CASE WHEN code = 9053 THEN 1 ELSE 0 END:把触发分组变化的行标记为1,其他行标记为0
  • SUM() OVER(...):从当前id分组的第一行到当前行累计求和,这样每次遇到9053时,总和就会加1,形成新的分组ID;后续的行都会继承这个ID,直到下一个9053出现

查询结果里,id=1082的前两行group_id是1,后两行是2;id=1196的所有行因为没有触发条件,group_id都是1,完全符合连续行分组的需求。

解法2:当时间间隔超过阈值时开启新分组

如果你的触发条件是连续两行的时间间隔超过N分钟(比如3分钟),只需要修改CASE里的判断逻辑即可:

SELECT 
    ukey,
    id,
    code,
    create_date,
    -- +1是因为第一行没有前一行,默认累计和为0,加1让分组从1开始
    SUM(CASE 
        WHEN DATEDIFF(MINUTE, LAG(create_date) OVER(PARTITION BY id ORDER BY create_date), create_date) > 3 
        THEN 1 
        ELSE 0 
    END) OVER (
        PARTITION BY id 
        ORDER BY create_date 
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) + 1 AS group_id
FROM YourTable
ORDER BY id, create_date;

逻辑解释:

  • LAG(create_date) OVER(...):获取当前行的前一行的create_date值
  • DATEDIFF(MINUTE, ...):计算当前行和前一行的时间间隔(分钟数)
  • 当间隔超过3分钟时标记为1,累计求和后得到分组ID,加1是为了让第一行的分组ID从1开始,而不是0

通用思路

不管你的触发条件是什么,核心都是:

  1. 用CASE语句把触发分组变化的行标记为1,其他行标记为0
  2. 用SUM() OVER(PARTITION BY 分组字段 ORDER BY 排序字段)来累计这些标记值,得到连续的分组ID

只要你能把“触发条件”转化为CASE里的判断,就能轻松实现需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:54:12