Q: SQLite-запрос для поиска островков в данных (то есть последовательных строк, где значение достигло определенного порога) - PullRequest
0 голосов
/ 04 января 2019

У меня есть база данных SQLite с, скажем, процентом мертвых клеток, обнаруженных в злокачественном организме с течением времени (ПРИМЕЧАНИЕ: значения столбца времени были заменены на простые числа для удобства чтения).

id  time                deadcellspercent
1   000000001000000000  35
2   000000002000000000  54
3   000000003000000000  31
4   000000004000000000  15
5   000000005000000000  38
6   000000006000000000  70
7   000000007000000000  28
8   000000008000000000  13
9   000000009000000000  99
10  000000010000000000  51

Я хочу создать запрос SQLite, который будет возвращать диапазон времени, когда процентное значение упало выше определенного порогового значения.Например, если я скажу, что я хочу, чтобы порог был> = 20, то результат запроса должен вернуть:

ts_start            ts_end
000000001000000000  000000003000000000
000000005000000000  000000007000000000
000000009000000000  000000010000000000

Как мне сформировать запрос для этого?Я читал о таких темах, как «оконные функции SQLite», «проблема гапсов и островков» и «аналитические функции», но я новичок в SQL и не могу понять, как получить желаемый результат.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 04 января 2019

Вы были на правильном пути с оконными функциями, пробелами и островками.

Сначала давайте возьмем ваши примерные данные и наполним их таблицей:

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; см. Объяснения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...