在mysql中选择连续的记录块

时间:2012-11-19 15:26:17

标签: mysql sql algorithm

我在MySql 5中有一个电话号码表。简单的结构是

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

1 个答案:

答案 0 :(得分:14)

有一个简单的方法可以将连续的条目折叠到一个组中。如果按(row_number - entry)分组,则连续的条目将最终位于同一组中。这是一个展示我的意思的例子:

<强>查询

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 |

注意连续的条目如何具有PHONENUM - @CURROW的相同值。如果我们将该列分组,并选择min&amp;每个组的最大值,你有摘要(有一个例外:如果START = END,你可以用NULL替换END值,如果这是一个要求):

<强>查询

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 |

演示:http://www.sqlfiddle.com/#!2/59b04/5