数据库中如何使用SQL查询连续数字并且统计连续个数

本文通过一组手机号数据进行分析,展示了如何找出连续的手机号段,并统计每个区间的数量。使用SQL查询来实现这一目标,有助于理解手机号分配模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[b]seven 表[/b]
[table]
|mobile_parent|mobile|
|1352162803x|900|
|1352162803x|923|
|1352162803x|924|
|1352162803x|925|
|1352162803x|927|
|1352162803x|929|
|1352162803x|931|
|1352162803x|934|
|1352162803x|935|
|1352162803x|937|
|1352162803x|938|
|1352162803x|939|
[/table]


SELECT b.mobile_parent, MIN (b.mobile) Start_HM, MAX (b.mobile) End_HM, count(*) as ccount
FROM (
SELECT a.mobile_parent,a.mobile, TO_NUMBER (a.mobile - ROWNUM) cc
FROM (
SELECT *
FROM seven
ORDER BY mobile_parent, mobile
) a
) b
GROUP BY b.mobile_parent, b.cc
having count(*) > 1


[table]
|开始| 结束 |个数|
|923 | 925 | 3|
|934 | 935 | 2|
|937 | 939 | 3|
[/table]
### SQL 查询字段中至少连续出现 N 次的数字实现方式 #### 方法一:基于 `ROWNUM` 的 Oracle 解决方案 在 Oracle 数据库中,可以利用 `ROWNUM` 来标记每一行记录的位置,并通过排序来识别连续出现的数值。具体做法如下: 1. 首先按目标列(如 `num`)以及 `ROWNUM` 排序,生成一个新的序列号作为辅助列。 2. 计算每组连续值之间的差值,如果某个数连续多次,则其对应的差值会保持一致。 以下是具体的 SQL 实现: ```sql WITH numbered_rows AS ( SELECT num, ROWNUM AS row_num, ROW_NUMBER() OVER (ORDER BY ID) AS rn FROM lx_01 ), grouped_rows AS ( SELECT num, row_num - rn AS group_id FROM numbered_rows ) SELECT num, COUNT(*) AS count FROM grouped_rows GROUP BY num, group_id HAVING COUNT(*) >= :N; ``` 此方法的核心在于计算 `row_num - rn` 的差值,从而分组统计连续出现次数[^1]。 --- #### 方法二:使用窗口函数 `LAG/LEAD` 对于更复杂的场景或者跨数据库兼容的情况,可以通过窗口函数 `LAG` 或 `LEAD` 来比较当前行与其前后的行是否相等。这种方法适用于大多数现代关系型数据库(如 MySQL 8.0+, PostgreSQL, SQL Server, Oracle 等)。 以下是一个通用的例子: ```sql WITH lagged_data AS ( SELECT Num, LAG(Num, 1) OVER (ORDER BY ID) AS prev_Num1, LAG(Num, 2) OVER (ORDER BY ID) AS prev_Num2 FROM logs ) SELECT DISTINCT Num FROM lagged_data WHERE Num = prev_Num1 AND Num = prev_Num2; ``` 该查询逻辑是通过对比当前行与前面两行的值是否相同,判断是否存在连续三次相同的数字。要扩展到任意长度 `N`,只需动态调整 `LAG` 函数中的偏移量即可[^2]。 --- #### 方法三:自定义变量法(MySQL 特定) 在某些不支持复杂窗口函数的老版本数据库(如早期版 MySQL),可借助用户定义变量完成类似功能。例如: ```sql SET @prev := NULL; SET @cnt := 0; SELECT Num, COUNT(*) AS freq FROM ( SELECT CASE WHEN @prev = Num THEN @cnt := @cnt + 1 ELSE @cnt := 1 END AS cnt_in_group, CASE WHEN @prev <> Num THEN @prev := Num END AS dummy, Num FROM logs ORDER BY ID ) t WHERE cnt_in_group >= :N GROUP BY Num; ``` 这里的关键点是对每次迭代的结果进行累加计数,当遇到新值时重置计数器[^3]。 --- ### 总结 以上三种方法分别针对不同环境提供了解决方案。其中,第一种适合纯 Oracle 场景;第二种具有较好的跨平台适应能力;第三种则专用于旧版 MySQL 用户群。实际应用时需根据所使用的 DBMS 类型及其特性选择最合适的策略。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值