LINUX.ORG.RU

Поиск допустимых интервалов

 


0

2

Есть таблица дат - одна колонка с датой. Разные часы в дне, какой-то час может быть пропущен.
25.10.2017 9:00:00
25.10.2017 10:00:00
25.10.2017 12:00:00
25.10.2017 13:00:00
25.10.2017 14:00:00
25.10.2017 15:00:00
25.10.2017 16:00:00
26.10.2017 8:00:00
26.10.2017 9:00:00
26.10.2017 10:00:00
26.10.2017 11:00:00
26.10.2017 13:00:00
26.10.2017 14:00:00
26.10.2017 15:00:00
26.10.2017 16:00:00

Нужно найти конец и начало интервала в дне по двум условиям:
1) продолжительность интервала в часах
2) Максимально допустимое количество пропущенных часов, которые могут быть проигнорированы.

Т.е. если есть в таблице часы 9,10,12,13,14, нужно собрать интервал в 5 часов, но максимально допустимый пропуск - 2 часа, то этот интервал подходит.

Не могу придумать алгоритм, помогите мыслями.

★★★★★

Последнее исправление: bvn13 (всего исправлений: 4)

Нужно найти конец и начало интервала в дне по двум условиям:

Если нужен один интервал, но их окажется несколько, то как быть?

Лучше опиши для чего это нужно, а то сам ты задачи формулируешь хреново.

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

Знакомый какие-то интервалы считает для производства. Задал задачку на подумать. Так что я не скажу, для чего конкретно это нужно.

Если нужен один интервал, но их окажется несколько, то как быть?

Это норма, пусть будет много строк в результате

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

Например самый топорный алгоритм (pseudocode):
внешнего цикла не написал, лень :)

last_hour = lines[0]
skiped_hour = 0
sum_hour = 0
for(hour in lines[1:]):
  if hour - last_hour + skiped_hour > 5:
    # скипаем до следующего цикла
  sum_hour += 1
  skiped_hour += hour - last_hour -1
как-то так, идея думаю понятна

anonymous
()

строишь эталонный список по нужным параметрам, дальше left join и всех делов.

Anoxemian ★★★★★
()

есть такая штука start_of_group

with a(x) as (values
('25.10.2017 9:00:00'),
('25.10.2017 10:00:00'),
('25.10.2017 12:00:00'),
('25.10.2017 13:00:00'),
('25.10.2017 14:00:00'),
('25.10.2017 15:00:00'),
('25.10.2017 16:00:00'),
('26.10.2017 8:00:00'),
('26.10.2017 9:00:00'),
('26.10.2017 10:00:00'),
('26.10.2017 11:00:00'),
('26.10.2017 13:00:00'),
('26.10.2017 14:00:00'),
('26.10.2017 15:00:00'),
('26.10.2017 16:00:00')),
t as (select to_timestamp(a.x, 'dd.mm.yyyy hh24:mi:ss') as t from a),
tt as (select t, extract(doy from t)::int as doy from t),
ttt as (select *, tt.t - lag(tt.t) over(partition by tt.doy order by tt.t) as delta from tt),
tttt as (select *, (delta is null or delta > '1 hour'::interval)::int as sog from ttt),
ttttt as (select *, sum(sog) over(order by tttt.t) as gid from tttt)

select min(t) as start, max(t) as end, gid 
from ttttt group by gid order by start

тут разжевано, можно короче записать.

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