2013-06-11 9 views
7

Mam tabeli z następującą definicjąJak znaleźć granice grup ciągłych numerów sekwencyjnych?

CREATE TABLE mytable 
    (
    id  INT IDENTITY(1, 1) PRIMARY KEY, 
    number BIGINT, 
    status INT 
) 

i przykładowe dane

INSERT INTO mytable 
VALUES (100,0), 
     (101,0), 
     (102,0), 
     (103,0), 
     (104,1), 
     (105,1), 
     (106,0), 
     (107,0), 
     (1014,0), 
     (1015,0), 
     (1016,1), 
     (1017,0) 

tylko patrząc na rzędy gdzie status = 0 jak mogę zwinąć wartości Number w zakresach sąsiadujących numerów sekwencyjnych i znaleźć początek i koniec każdego zakresu?

tj Na przykład dane wyniki byłyby

  FROM  to 
Number 100  103 
Number 106  107 
Number 1014  1015 
Number 1017  1017 
+0

Zrobiłem to wcześniej, kilka miesięcy temu. Nie sądzę, żebym zapisał zapytanie, ale może nadal znajdować się w moich lokalnych dziennikach. Trzymaj się. –

+3

google "luki w serwerze sql i wyspy" – OzrenTkalcecKrznaric

+0

Niestety nie mogę go znaleźć. –

Odpowiedz

25

Jak wspomniano w komentarzach jest to klasyczny luki i wyspy problem.

Rozwiązaniem spopularyzowanym przez Itzika Ben Gana jest wykorzystanie faktu, że ROW_NUMBER() OVER (ORDER BY number) - number pozostaje stałe w obrębie "wyspy" i nie może się pojawić na wielu wyspach.

WITH T 
    AS (SELECT ROW_NUMBER() OVER (ORDER BY number) - number AS Grp, 
       number 
     FROM mytable 
     WHERE status = 0) 
SELECT MIN(number) AS [From], 
     MAX(number) AS [To] 
FROM T 
GROUP BY Grp 
ORDER BY MIN(number) 

NB: Jeżeli number nie jest gwarancją wyjątkowy zastąpić ROW_NUMBER z DENSE_RANK w powyższym kodzie.

+0

+1: Tak, to jest najlepsze podejście. Nie trzeba przeklętych kursorów ani nieskutecznych rekurencji. – RBarryYoung

+0

Twój geniusz! Bardzo dziękuję –

+3

Oto jedno z miejsc, o których mówi Itzak: http://www.sqlmag.com/article/tsql3/calculating-concurrent-sessions-part-3. Nie wspomnę o tym, komu się podoba, rozwiązując go (oprócz Bena Flanaghana i Arnolda Fribble'a). ;-) – RBarryYoung

Powiązane problemy