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

SQL统计连续出现的1的数量:非连续ID场景下的实现方案

统计连续ID且状态为1的序列

这个场景我之前处理过好多次,核心思路就是用窗口函数给连续的记录打上分组标记,再聚合出每个序列的起止ID就行。我给你一步步拆解:

假设你的表名叫your_table,包含两个关键字段:ID(非连续的数值型字段)和status(标记是否为1的字段)。

步骤1:筛选有效数据

先把所有status=1的记录单独拎出来,排除其他状态的干扰,避免影响连续序列的判断:

WITH filtered_data AS (
    SELECT ID
    FROM your_table
    WHERE status = 1
)

步骤2:给连续ID打分组标签

接下来用LAG()窗口函数获取当前行的前一个ID,计算两者的差值。如果差值不等于1,说明当前行是一个新序列的起点。我们用累积求和生成分组ID,让连续的ID归到同一个组:

, grouped_data AS (
    SELECT 
        ID,
        -- 当当前ID和前一个ID不连续时,标记为新分组起点,累积求和得到组ID
        SUM(CASE WHEN ID - LAG(ID, 1, ID-1) OVER (ORDER BY ID) != 1 THEN 1 ELSE 0 END) 
            OVER (ORDER BY ID) AS sequence_group
    FROM filtered_data
)

这里LAG(ID, 1, ID-1)的第三个参数是默认值,专门处理第一行没有前序ID的情况,保证第一行如果是1的话,不会被误判为新分组。

步骤3:聚合得到序列起止

最后按分组ID聚合,取每个组的最小和最大ID,就是你要的连续序列:

SELECT 
    MIN(ID) AS start_id,
    MAX(ID) AS end_id
FROM grouped_data
GROUP BY sequence_group
ORDER BY start_id;

补充说明

如果你的“连续出现的1”是指status连续为1但ID不一定连续(比如ID跳号但status一直是1也算一个序列),那只要把判断逻辑改成对比前一行的status就行:

SUM(CASE WHEN status != LAG(status, 1, 0) OVER (ORDER BY ID) THEN 1 ELSE 0 END) 
    OVER (ORDER BY ID) AS sequence_group

不过看你的例子是ID连续的区间,所以第一种方法更贴合你的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:35:35