I have a table with the following definition
CREATE TABLE mytable
(
id INT IDENTITY(1, 1) PRIMARY KEY,
number BIGINT,
status INT
)
and example data
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)
Looking only at the rows where status = 0
how can I collapse the Number
values into ranges of contiguous sequential numbers and find the start and end of each range?
i.e. For the example data the results would be
FROM to
Number 100 103
Number 106 107
Number 1014 1015
Number 1017 1017
As mentioned in the comments this is a classic gaps and islands problem.
A solution popularized by Itzik Ben Gan is to use the fact that ROW_NUMBER() OVER (ORDER BY number) - number
remains constant within an "island" and cannot appear in multiple islands.
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: If number
is not guaranteed to be unique replace ROW_NUMBER
with DENSE_RANK
in the code above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With