Oracle SQL查询实现连续序列的起止值及计数
Oracle SQL实现连续序列分组统计
当然可以直接用Oracle SQL实现这个需求!这是处理连续数值分组的经典场景,完全不需要借助Java遍历,用窗口函数就能轻松搞定。
核心思路
要找出连续的数字序列,关键是给每个连续的序列分配一个唯一的分组标识。具体方法是:
- 给每个
seq按顺序生成行号(或排名) - 用
seq减去这个行号,连续的数字会得到相同的结果(因为连续数的增长和行号的增长同步),这个结果就是分组的依据
举个例子,你提供的seq数据对应的计算结果:
| seq | ROW_NUMBER() | seq - ROW_NUMBER() |
|---|---|---|
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 7 | 4 | 3 |
| 8 | 5 | 3 |
| 9 | 6 | 3 |
| 14 | 7 | 7 |
| 19 | 8 | 11 |
| 20 | 9 | 11 |
可以看到,连续的seq对应的seq - ROW_NUMBER()值完全相同,这就是我们的分组ID。
完整SQL代码
SELECT MIN(seq) AS "Start", MAX(seq) AS "End", COUNT(*) AS "Count" FROM ( SELECT seq, seq - ROW_NUMBER() OVER (ORDER BY seq) AS group_id FROM TB1 ) grouped_data GROUP BY group_id ORDER BY "Start";
代码解释
子查询
grouped_data:ROW_NUMBER() OVER (ORDER BY seq):按seq的升序给每条记录分配一个唯一的行号- 计算
seq - 行号得到group_id,相同group_id的记录属于同一个连续序列
外层查询:
- 按
group_id分组,用MIN(seq)获取序列的起始值,MAX(seq)获取结束值 COUNT(*)统计该序列包含的数字个数- 最后按起始值排序,保证结果顺序和原数据一致
- 按
测试验证
用你提供的TB1数据执行上述SQL,会得到完全符合期望的结果:
| Start | End | Count |
|---|---|---|
| 1 | 3 | 3 |
| 7 | 9 | 3 |
| 14 | 14 | 1 |
| 19 | 20 | 2 |
补充说明
如果你的seq列存在重复值,ROW_NUMBER()可能会导致分组错误,这时可以改用DENSE_RANK()代替ROW_NUMBER(),确保重复的seq也能被分到同一个组里。
内容的提问来源于stack exchange,提问作者mallikarjun
相关产品推荐
相关产品推荐

