Вы были на правильном пути с оконными функциями, пробелами и островками.
Сначала давайте возьмем ваши примерные данные и наполним их таблицей:
CREATE TABLE cells(id INTEGER PRIMARY KEY, time TEXT, deadcellspercent INTEGER);
INSERT INTO cells VALUES(1,'000000001000000000',35);
INSERT INTO cells VALUES(2,'000000002000000000',54);
INSERT INTO cells VALUES(3,'000000003000000000',31);
INSERT INTO cells VALUES(4,'000000004000000000',15);
INSERT INTO cells VALUES(5,'000000005000000000',38);
INSERT INTO cells VALUES(6,'000000006000000000',70);
INSERT INTO cells VALUES(7,'000000007000000000',28);
INSERT INTO cells VALUES(8,'000000008000000000',13);
INSERT INTO cells VALUES(9,'000000009000000000',99);
INSERT INTO cells VALUES(10,'000000010000000000',51);
Один возможный запрос (Который использует оконные функции и, следовательно, требует обновленной версии sqlite - 3.25 или новее):
WITH islands AS (SELECT id, time
, row_number() OVER w1 - row_number() OVER w2 AS diff
, deadcellspercent >= 20 AS wanted
FROM cells
WINDOW w1 AS (ORDER BY time)
, w2 AS (PARTITION BY deadcellspercent >= 20 ORDER BY time))
SELECT min(time) AS ts_start, max(time) AS ts_end
FROM islands
WHERE wanted = 1
GROUP BY diff
ORDER BY diff;
производит:
ts_start ts_end
------------------ ------------------
000000001000000000 000000003000000000
000000005000000000 000000007000000000
000000009000000000 000000010000000000
(в значительной степени под влиянием этот пост на стековом обмене DBA; см. Объяснения).