如何在SQL中查找逐位递增或递减步长为1的数字序列值
SQL筛选逐位连续递增/递减数字字符串方案
需求描述
需筛选长度在3位到10位之间的数字字符串,规则为字符串每一位相邻数字严格逐位+1递增(如123、0123456789)或严格逐位-1递减(如321、9876543210),存在相邻位数值重复、跳变的字符串不符合要求。
测试数据
测试用临时表数据插入语句如下:
INSERT INTO #TmpTbl Values ('12345') ,('45678') ,('44569') ,('987654') ,('748376') ,('123') ,('0123456789') ,('9876543210')
预期输出
符合规则的结果如下:
- 12345
- 45678
- 987654
- 123
- 0123456789
- 9876543210
实现代码(SQL Server 适用)
核心逻辑为拆分字符串逐位计算相邻数字差值,判断差值是否全部为1或全部为-1:
WITH SplitDigit AS ( SELECT num_col AS target_str, CAST(SUBSTRING(num_col, pos.id, 1) AS INT) AS digit_val, pos.id AS digit_pos FROM #TmpTbl -- 生成1-10的位置序列,匹配最长10位的字符串长度 CROSS APPLY ( SELECT TOP 10 ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS id FROM sys.all_columns ) pos WHERE pos.id <= LEN(num_col) AND LEN(num_col) BETWEEN 3 AND 10 -- 提前过滤长度不符合要求的数据 ), CalcAdjacentDiff AS ( SELECT target_str, digit_val - LAG(digit_val) OVER(PARTITION BY target_str ORDER BY digit_pos) AS diff FROM SplitDigit ) SELECT DISTINCT target_str FROM CalcAdjacentDiff GROUP BY target_str HAVING -- 所有相邻位差值为1,即严格递增 SUM(CASE WHEN diff = 1 THEN 1 ELSE 0 END) = LEN(target_str) - 1 OR -- 所有相邻位差值为-1,即严格递减 SUM(CASE WHEN diff = -1 THEN 1 ELSE 0 END) = LEN(target_str) - 1
逻辑说明
- 第一步拆分字符串每一位为单独行,标记数字所在位置,同时提前筛掉长度不在3~10位区间的无效数据,减少后续计算量
- 第二步通过
LAG窗口函数取同个字符串前一位的数字,计算相邻两位的差值 - 最后按字符串分组统计:如果相邻位差值为1的总个数等于字符串长度减1,说明是严格连续递增;如果相邻位差值为-1的总个数等于字符串长度减1,说明是严格连续递减,两类数据即为符合要求的结果。
内容的提问来源于stack exchange,提问作者Doolius
相关产品推荐
相关产品推荐

