如何查询tblProduct表SerialNum字段连续序列号的区间最值
连续序列号区间识别方案
实现原理
这是经典的**间隙与岛屿(Gaps and Islands)**问题,不需要写循环逐行比对,用窗口函数即可一次性完成所有连续段的识别,核心逻辑:
- 序列号固定为「5位补零数字+1位字母」结构,不同字母后缀的序列号互不连通,必须按后缀拆分分组
- 同后缀组内将前5位转成数值后升序排列,生成连续行号
- 用「数值部分 - 行号」生成分组标记:同一连续段内所有序列号的该计算结果完全一致,断号位置该值会跳变,自动完成连续段拆分
- 按分组标记聚合取每个段的最小、最大序列号,按规则格式化输出即可
可直接运行的SQL代码
支持MySQL 8.0+、SQL Server、PostgreSQL等所有支持窗口函数的数据库环境:
WITH SerialParsed AS ( SELECT SerialNum, CAST(LEFT(SerialNum, 5) AS UNSIGNED) AS NumPart, RIGHT(SerialNum, 1) AS Suffix FROM tblProduct ), SerialGrouped AS ( SELECT SerialNum, Suffix, NumPart, ROW_NUMBER() OVER (PARTITION BY Suffix ORDER BY NumPart) AS RowSeq, NumPart - ROW_NUMBER() OVER (PARTITION BY Suffix ORDER BY NumPart) AS GroupFlag FROM SerialParsed ) SELECT CASE WHEN MIN(SerialNum) = MAX(SerialNum) THEN MIN(SerialNum) ELSE CONCAT(MIN(SerialNum), ' - ', MAX(SerialNum)) END AS SerialRange FROM SerialGrouped GROUP BY Suffix, GroupFlag ORDER BY Suffix, MIN(NumPart);
注:如果是PostgreSQL、SQL Server环境,把UNSIGNED改成INTEGER即可直接运行。
测试数据集运行结果
针对提供的测试数据,上述代码输出完全匹配预期:
00001A - 00014A 00175A - 00180A 00540A - 00549A 12345A - 12349A 04500B - 04503B 04522B - 04529B 04595B 04627B - 04631B
方案优势
- 不需要游标、循环逐行遍历记录,单次查询即可完成全量数据计算,性能远高于记录集循环方案
- 自动识别所有连续段和孤立序列号,不会出现跨区间匹配漏判的问题
- 严格遵守区间判定规则:只有中间无断号的连续序列号才会被归为同一区间
内容的提问来源于stack exchange,提问作者Zeella
相关产品推荐
相关产品推荐

