2012-11-19 13 views
6

Mam tabelę w MySql 5 numerów telefonów. Prosta konstrukcja jestWybieranie ciągłego bloku rekordów w mysql

Accounts 
id varchar(32) NOT NULL 

Zapisy są następujące

27100070000 
27100070001 
27100070002 
27100070003 
27100070004 
27100070005 
27100070008 
27100070009 
27100070012 
27100070015 
27100070016 
27100070043 

muszę uporządkować te dane i grupowych ciągłych bloków numerów do zakresów numerów. Jestem otwarty na wdrożenie rozwiązania w języku C# LINQ, ale MySql po stronie serwera jest pierwszą nagrodą. Czy istnieje sposób w MySql, aby zebrać te dane tak, aby wynik był jak poniżej?

Start  | End 
------------------------- 
27100070000 | 27100070005 
27100070008 | 27100070009 
27100070012 | 27100070015 
27100070016 | NULL 
27100070043 | NULL 
+0

Nie wiem o SQL, ale z PHP (lub którykolwiek z kuzynów rzeczywiście), który jest trywialny. –

Odpowiedz

13

Istnieje prosta sztuczka do zwijania kolejnych wpisów w jedną grupę. Jeśli pogrupujesz według (numer_elementu - wpis), wpisy, które są kolejne, znajdą się w tej samej grupie. Oto przykład wykazanie co mam na myśli:

Zapytanie:

SELECT phonenum, @curRow := @curRow + 1 AS row_number, phonenum - @curRow 
from phonenums p 
join (SELECT @curRow := 0) r 

Wyniki:

| 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 | 

Wskazówki jak wpisy, które są z kolei wszystkie mają taką samą wartość dla PHONENUM - @CURROW. Jeśli mamy grupę na tej kolumnie, a następnie wybierz min & max każdej grupie, masz podsumowanie (z jednym wyjątkiem: można zastąpić wartości końcowej z NULL jeśli start = END, jeśli to wymagane):

Query:

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 

Wyniki:

| MIN(PHONENUM) | MAX(PHONENUM) | 
--------------------------------- 
| 27100070000 | 27100070005 | 
| 27100070008 | 27100070009 | 
| 27100070012 | 27100070012 | 
| 27100070015 | 27100070016 | 
| 27100070040 | 27100070040 | 

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

+0

dzięki za genialną odpowiedź! Jak mogę przygotować się na sytuację, w której abonenckie może być nie numeryczne, takie jak gdzie może być del_2712212 lub adres IP? Po prostu chcę teraz wyłączyć te "brudne" dane. –

+1

@Zahir: Po prostu wymyśl filtr, aby zostawić te dane i umieść je w klauzuli "where" w zapytaniu wewnętrznym. Powinieneś być w stanie znaleźć liczne przykłady w Internecie, jak sprawdzić, czy dane są numeryczne. Być może trzeba będzie również rzucić go, aby zapytanie działało poprawnie, ponieważ założyłem, że dane wejściowe były już typem liczbowym. – mellamokb

Powiązane problemy