在mysql中选择连续记录块
我在MySql 5中有一个电话号码表。简单的结构是在mysql中选择连续记录块,mysql,sql,algorithm,Mysql,Sql,Algorithm,我在MySql 5中有一个电话号码表。简单的结构是 Accounts id varchar(32) NOT NULL 记录如下: 27100070000 27100070001 27100070002 27100070003 27100070004 27100070005 27100070008 27100070009 27100070012 27100070015 27100070016 27100070043 我需要对这些数据进行排序,并将连续的数字块分组到数字范围中。我愿意用C#LIN
Accounts
id varchar(32) NOT NULL
记录如下:
27100070000
27100070001
27100070002
27100070003
27100070004
27100070005
27100070008
27100070009
27100070012
27100070015
27100070016
27100070043
我需要对这些数据进行排序,并将连续的数字块分组到数字范围中。我愿意用C#LINQ实现这个解决方案,但服务器端MySql是第一名。在MySql中有没有一种方法可以汇总这些数据,以便输出如下所示
Start | End
-------------------------
27100070000 | 27100070005
27100070008 | 27100070009
27100070012 | 27100070015
27100070016 | NULL
27100070043 | NULL
有一个简单的技巧可以将连续条目折叠成一个组。如果按(行编号-条目)分组,则连续的条目将在同一组中结束。下面是一个示例,演示我的意思: 查询:
SELECT phonenum, @curRow := @curRow + 1 AS row_number, phonenum - @curRow
from phonenums p
join (SELECT @curRow := 0) r
| PHONENUM | ROW_NUMBER | PHONENUM - @CURROW |
-------------------------------------------------
| 27100070000 | 1 | 27100069999 |
| 27100070001 | 2 | 27100069999 |
| 27100070002 | 3 | 27100069999 |
| 27100070003 | 4 | 27100069999 |
| 27100070004 | 5 | 27100069999 |
| 27100070005 | 6 | 27100069999 |
| 27100070008 | 7 | 27100070001 |
| 27100070009 | 8 | 27100070001 |
| 27100070012 | 9 | 27100070003 |
| 27100070015 | 10 | 27100070005 |
| 27100070016 | 11 | 27100070005 |
| 27100070040 | 12 | 27100070028 |
select min(phonenum), max(phonenum) from
(
SELECT phonenum, @curRow := @curRow + 1 AS row_number
from phonenums p
join (SELECT @curRow := 0) r
) p
group by phonenum - row_number
| MIN(PHONENUM) | MAX(PHONENUM) |
---------------------------------
| 27100070000 | 27100070005 |
| 27100070008 | 27100070009 |
| 27100070012 | 27100070012 |
| 27100070015 | 27100070016 |
| 27100070040 | 27100070040 |
结果:
SELECT phonenum, @curRow := @curRow + 1 AS row_number, phonenum - @curRow
from phonenums p
join (SELECT @curRow := 0) r
| PHONENUM | ROW_NUMBER | PHONENUM - @CURROW |
-------------------------------------------------
| 27100070000 | 1 | 27100069999 |
| 27100070001 | 2 | 27100069999 |
| 27100070002 | 3 | 27100069999 |
| 27100070003 | 4 | 27100069999 |
| 27100070004 | 5 | 27100069999 |
| 27100070005 | 6 | 27100069999 |
| 27100070008 | 7 | 27100070001 |
| 27100070009 | 8 | 27100070001 |
| 27100070012 | 9 | 27100070003 |
| 27100070015 | 10 | 27100070005 |
| 27100070016 | 11 | 27100070005 |
| 27100070040 | 12 | 27100070028 |
select min(phonenum), max(phonenum) from
(
SELECT phonenum, @curRow := @curRow + 1 AS row_number
from phonenums p
join (SELECT @curRow := 0) r
) p
group by phonenum - row_number
| MIN(PHONENUM) | MAX(PHONENUM) |
---------------------------------
| 27100070000 | 27100070005 |
| 27100070008 | 27100070009 |
| 27100070012 | 27100070012 |
| 27100070015 | 27100070016 |
| 27100070040 | 27100070040 |
请注意,连续的条目在PHONENUM-@CURROW
中的值是如何相同的。如果我们在该列上分组,并选择每个组的最小值和最大值,您就有了摘要(只有一个例外:如果开始=结束,您可以将结束值替换为NULL
If START=END,如果这是一个要求):
查询:
SELECT phonenum, @curRow := @curRow + 1 AS row_number, phonenum - @curRow
from phonenums p
join (SELECT @curRow := 0) r
| PHONENUM | ROW_NUMBER | PHONENUM - @CURROW |
-------------------------------------------------
| 27100070000 | 1 | 27100069999 |
| 27100070001 | 2 | 27100069999 |
| 27100070002 | 3 | 27100069999 |
| 27100070003 | 4 | 27100069999 |
| 27100070004 | 5 | 27100069999 |
| 27100070005 | 6 | 27100069999 |
| 27100070008 | 7 | 27100070001 |
| 27100070009 | 8 | 27100070001 |
| 27100070012 | 9 | 27100070003 |
| 27100070015 | 10 | 27100070005 |
| 27100070016 | 11 | 27100070005 |
| 27100070040 | 12 | 27100070028 |
select min(phonenum), max(phonenum) from
(
SELECT phonenum, @curRow := @curRow + 1 AS row_number
from phonenums p
join (SELECT @curRow := 0) r
) p
group by phonenum - row_number
| MIN(PHONENUM) | MAX(PHONENUM) |
---------------------------------
| 27100070000 | 27100070005 |
| 27100070008 | 27100070009 |
| 27100070012 | 27100070012 |
| 27100070015 | 27100070016 |
| 27100070040 | 27100070040 |
结果:
SELECT phonenum, @curRow := @curRow + 1 AS row_number, phonenum - @curRow
from phonenums p
join (SELECT @curRow := 0) r
| PHONENUM | ROW_NUMBER | PHONENUM - @CURROW |
-------------------------------------------------
| 27100070000 | 1 | 27100069999 |
| 27100070001 | 2 | 27100069999 |
| 27100070002 | 3 | 27100069999 |
| 27100070003 | 4 | 27100069999 |
| 27100070004 | 5 | 27100069999 |
| 27100070005 | 6 | 27100069999 |
| 27100070008 | 7 | 27100070001 |
| 27100070009 | 8 | 27100070001 |
| 27100070012 | 9 | 27100070003 |
| 27100070015 | 10 | 27100070005 |
| 27100070016 | 11 | 27100070005 |
| 27100070040 | 12 | 27100070028 |
select min(phonenum), max(phonenum) from
(
SELECT phonenum, @curRow := @curRow + 1 AS row_number
from phonenums p
join (SELECT @curRow := 0) r
) p
group by phonenum - row_number
| MIN(PHONENUM) | MAX(PHONENUM) |
---------------------------------
| 27100070000 | 27100070005 |
| 27100070008 | 27100070009 |
| 27100070012 | 27100070012 |
| 27100070015 | 27100070016 |
| 27100070040 | 27100070040 |
演示:我不知道SQL,但是对于PHP(或者任何类似的东西)来说,这都是微不足道的。谢谢你的精彩回答!如何应对phonenum可能是非数字的情况,例如它可能是del_2712212或ip地址?我现在只想排除这个“脏”数据。@Zahir:只需想出一个过滤器来删除该数据,并将其包含在内部查询的
where
子句中。您应该能够在web上找到许多如何验证数据是否为数字的示例。您可能还需要将其转换为查询才能正常工作,因为我假设输入数据已经是数字类型。