Reputation: 120
Can you help me find first and the last id in the squences where Active is true. So from this result
id | Active
---------------
1 | false
2 | false
3 | true
4 | true
5 | false
6 | false
7 | false
8 | true
9 | true
10 | false
11 | false
12 | true
13 | true
14 | true
I’ll need all continous sequences (where active is true) with start and end id
startId | endId
------------------------
3 | 4
8 | 9
12 | 14
Upvotes: 3
Views: 54
Reputation: 72165
This is a typical gaps and islands problem. Use ROW_NUMBER
to identify groups of sequential records having the same Active
value:
SELECT MIN(id) AS startId, MAX(id) AS endId
FROM (
SELECT id, Active,
ROW_NUMBER() OVER (ORDER BY id) -
ROW_NUMBER() OVER (PARTITION BY Active ORDER BY id) AS grp
FROM mytable) AS t
WHERE Active = 'true'
GROUP BY grp
The outer query simply filters out Active = false
records and groups by grp
calculated field, in order to get startId
and endId
.
Upvotes: 5
Reputation: 35780
You can do this with island solution:
DECLARE @t TABLE
(
id INT ,
Active VARCHAR(10)
)
INSERT INTO @t
VALUES ( 1, 'false' ),
( 2, 'false' ),
( 3, 'true' ),
( 4, 'true' ),
( 5, 'false' ),
( 6, 'false' ),
( 7, 'false' ),
( 8, 'true' ),
( 9, 'true' ),
( 10, 'false' ),
( 11, 'false' ),
( 12, 'true' ),
( 13, 'true' ),
( 14, 'true' );
WITH cte
AS ( SELECT * ,
ROW_NUMBER() OVER ( ORDER BY id )
- ROW_NUMBER() OVER ( PARTITION BY Active ORDER BY id ) rn
FROM @t
)
SELECT MIN(id) AS StartID ,
MAX(id) AS EndID
FROM cte
WHERE Active = 'true'
GROUP BY rn
The idea behind is that you just assign some values to islands. Look here what you get in cte:
id Active rn
1 false 0
2 false 0
3 true 2
4 true 2
5 false 2
6 false 2
7 false 2
8 true 5
9 true 5
10 false 4
11 false 4
12 true 7
13 true 7
14 true 7
Upvotes: 6