LINUX.ORG.RU

помогите составить SQL запрос SQLite

 ,


1

1

Есть база данных, в ней есть поле с числом секунд с начала эпохи, оно соответствует времени генерации данных. надо найти все промежутки времени, когда данных не было более 20 секунд, и отдельно интервалы, когда не было данных более 10 минут. Идеи?

★★★★★

то есть по сути найти все дырки, длиной более 20 и более 600 Я плохо понимаю, как тут подселект организовать можно...

slapin ★★★★★
() автор топика

нужно делать join, в котором каждая строка из таблицы будет объединяться с предыдущей строкой, вычислять разницу и по разнице группировать/фильтровать

Harald ★★★★★
()

Так может?

SELECT * FROM `db` AS first WHERE NOT EXISTS (SELECT 1 FRM `db` WHERE time > first.time AND time - first.time < 20*1000 LIMIT 1);
Только это наверно дофига медленно будет.

Kalashnikov ★★★
()
Ответ на: комментарий от Harald

А писал я это по-твоему собачьим вальсом по клавиатуре?

Как-то работало...

ilya@home:~/tmp$ sqlite3 db
sqlite> create table tb (id int, time int);
sqlite> insert into tb values(1, 10);
sqlite> insert into tb values(2, 15);
sqlite> insert into tb values(3, 35);
sqlite> SELECT * FROM tb AS first WHERE NOT EXISTS (SELECT 1 FROM tb WHERE time > first.time AND time - first.time < 10 LIMIT 1);
1|15
3|35

Kalashnikov ★★★
()
Ответ на: комментарий от Kalashnikov

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

slapin ★★★★★
() автор топика
Ответ на: комментарий от slapin

несколько минут
приемлимо

Это как-то странно)

Попробуй джойн как предлагает Harald, должно быть быстрее.

Kalashnikov ★★★
()

узрейте SQL код великого гуру и падите ниц )))))

sqlite> create table tb (id int, time int);
sqlite> insert into tb values(1, 10);
sqlite> insert into tb values(2, 11);
sqlite> insert into tb values(3, 15);
sqlite> insert into tb values(4, 36);
sqlite> insert into tb values(5, 37);
sqlite> insert into tb values(6, 638);

sqlite> select t1.id,(t1.time - t2.time) as timediff
   ...> from
   ...> tb as t1
   ...> join
   ...> tb as t2
   ...> on t1.id = t2.id + 1
   ...> where timediff > 20;
4|21
6|601
Harald ★★★★★
()
Ответ на: комментарий от Harald

предполагается что нумерация ключей id непрерывна и возрастает

Harald ★★★★★
()
Ответ на: комментарий от Harald

узрейте SQL код великого гуру и падите ниц )))))

В красном углу ринга - чемпион мира по SQL в легком весе, гуру Harald! В синем углу ринга - многообещающий претендент Kalashnikov! Рефери - ветеран SQL, уважаемый slapin!

Let's get ready to rumble!

Кстати, странно, что никто из бойцов не создал индекса по time.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

странно что никто не додумалсяя до добавления столбца с дельтой или следуюущим значением.

visual ★★★
()

так может просто руками пробежать по записям? кода на несколько строк, нет затрат на хранение лишних данных или «сложные» запросы

wota ★★
()

а разве не:

create table dat (
  value integer
);

SELECT
   A.value AS val,
   A.value - max(B.value) AS delta
FROM dat as A, dat as B
WHERE B.value<A.value 
GROUP BY A.value
HAVING delta<20
в HAVING 10,20 или какой там фильтр по разнице.

MKuznetsov ★★★★★
()
Ответ на: комментарий от slapin

при условии B.value<A.value, max(B.value) - это непосредственно предыдущее(меньшее) значение.

Вообще запрос достаточно типичный - см. cumulative sum, очень частая вещь во всяких бухгалтериях/финансах. Там вычисляется сумма всех предыдущих (sum), а вам надо разность с предыдущим (от max()) - обе они агрегирующие функции с примерно одинаковой скоростью.

MKuznetsov ★★★★★
()

Спасибо всем огромное за помощь! Проблема решена. Использовал запросы, предложенные Kalashnikov и MKuznetsov.

slapin ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.