Если у вас есть современная версия PG, вы можете делать все, что хотите, используя оконные функции (в моем примере вместо меток времени у меня целые числа, но это не имеет значения): я работаю над неоконной версией функции...
db=> select * from test1;
time | status
------+--------
1 | f
2 | f
3 | f
4 | t
5 | f
6 | f
7 | f
8 | t
9 | f
10 | t
(8 rows)
Вот запрос с оконными функциями:
WITH a AS (
SELECT time,rank() OVER (ORDER BY time)
FROM (
SELECT status, time, lag(status,1) OVER (ORDER BY time) AS ls
FROM test1
) AS x
WHERE status AND NOT ls
-- select where the current status is true, the previous is false
), -- a is now the endings of the slots
b AS (
SELECT time, rank() OVER (ORDER BY time)
FROM (
SELECT status, time, LAG(status,1)
OVER (ORDER BY time) AS ls
FROM test1
) AS x
WHERE (NOT status AND ls) OR (NOT status AND ls IS NULL)
) -- b is now the beginning of the slots
SELECT b.time as time1, a.time as time2 FROM a,b WHERE a.rank=b.rank;
time1 | time2
------+------
1 | 4
5 | 8
9 | 10
Вот вариант запроса для PG без оконных функций (на самом деле он короче, но менее понятен)
SELECT min(time) as time1, time2 FROM
(
SELECT time, status,
(
SELECT time FROM test1 AS y
WHERE y.time >= x.time
ORDER BY (x.status = y.status)::int, y.time ASC LIMIT 1
) AS time2
FROM test1 AS x WHERE NOT status
) AS y GROUP BY y.time2 ORDER BY time2;