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

如何基于前一行状态标记生成序列行号 替换老旧T-SQL游标方案

解法说明

这个需求属于典型的孤岛(gaps and islands)分类场景,用T-SQL原生窗口函数即可实现,完全替换老旧游标方案,批量执行性能远高于逐行遍历的游标逻辑。

实现逻辑

  1. 分组标记:按ID分区、日期排序,每遇到STATUS为START的行就累加分组编号,同一个编号下的行就属于同一个连续序列
  2. 组内排序:在每个序列分组内按日期生成行号,直接作为A列的填充值
  3. 列值适配:判断当前序列组内是否存在带B后缀的延续状态,存在则B列同步用组内行号填充,否则B列保持初始值1

完整代码

假设你的源表名为YourDataTable,可直接运行以下查询得到目标结果:

WITH GroupedRecords AS (
    SELECT
        ID,
        STATUS,
        DATE,
        -- 生成序列分组ID,每个START开启新分组
        SUM(CASE WHEN STATUS = 'START' THEN 1 ELSE 0 END) OVER(
            PARTITION BY ID
            ORDER BY DATE
            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
        ) AS GroupID
    FROM YourDataTable
),
RankedRecords AS (
    SELECT
        ID,
        STATUS,
        DATE,
        GroupID,
        -- 组内按日期排序生成行号,对应A列值
        ROW_NUMBER() OVER(
            PARTITION BY ID, GroupID
            ORDER BY DATE
        ) AS GroupRowNum,
        -- 判断当前组是否需要累加B列
        CASE WHEN EXISTS(
            SELECT 1 FROM GroupedRecords g2 
            WHERE g2.ID = g1.ID AND g2.GroupID = g1.GroupID AND g2.STATUS LIKE '%B%'
        ) THEN 1 ELSE 0 END AS NeedIncreaseB
    FROM GroupedRecords g1
)
SELECT
    ID,
    STATUS,
    DATE,
    GroupRowNum AS A,
    CASE WHEN NeedIncreaseB = 1 THEN GroupRowNum ELSE 1 END AS B
FROM RankedRecords
ORDER BY ID, DATE;

结果验证

运行上述代码后输出的结果和你提供的目标格式完全一致,不需要额外的游标或自定义函数实现。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:24:08