Postgresql группа по повторяющимся пунктам

Я использую postgresql для хранения исторических данных, поступающих с платформы RTLS. Данные о местоположении не собираются непрерывно. Historical_movements реализован в виде одной таблицы следующим образом (это упрощенная таблица, но достаточная для представления варианта использования):

User   Area   EnterTime               ExitTime
John   room1  2018-01-01 10:00:00     2018-01-01 10:00:05
Doe    room1  2018-01-01 10:00:00     2018-01-01 10:10:00
John   room1  2018-01-01 10:05:00     2018-01-01 10:10:00
Doe    room1  2018-01-01 10:20:00     2018-01-01 10:30:00
John   room2  2018-01-01 11:00:00     2018-01-01 11:05:00
John   room2  2018-01-01 11:08:00     2018-01-01 11:15:00
John   room1  2018-01-01 12:00:00     2018-01-01 12:08:00
John   room1  2018-01-01 12:10:00     2018-01-01 12:20:00
John   room1  2018-01-01 12:25:00     2018-01-01 12:25:00
John   room3  2018-01-01 12:30:00     2018-01-01 12:35:00
John   room3  2018-01-01 12:40:00     2018-01-01 12:50:00

Я ищу способ сделать запрос, показывающий, что пользователь находится в разных комнатах, объединять данные, относящиеся к одной комнате, и вычислять общее время пребывания следующим образом.

User  Area    EnterTime               ExitTime              ArregateTime
John  room1   2018-01-01 10:00:00     2018-01-01 10:10:00   00:10:00
John  room2   2018-01-01 11:00:00     2018-01-01 11:05:00   00:15:00
John  room1   2018-01-01 12:00:00     2018-01-01 12:25:00   00:25:00
John  room3   2018-01-01 12:30:00     2018-01-01 12:50:00   00:20:00
Doe   room1   2018-01-01 10:00:00     2018-01-01 10:30:00   00:30:00

Глядя на различные темы, я вполне уверен, что мне придется использовать лаг и разбиение по функциям, но не совсем понятно, как. Есть намеки? С наилучшими пожеланиями.

1 ответ

AggregateTime на самом деле не aggregate в вашем ожидаемом результате. Кажется, разница между max_time а также min_time для каждого block где каждый блок состоит из смежных строк с одинаковыми (users, area),

with block as(
    select users, area, entertime, exittime,     
         (row_number() over (order by users, entertime) -
          row_number() over (partition by users, area order by entertime)
         ) as grp
    from your_table
    order by 1,2,3
)
select users, area, entertime, exittime, (exittime - entertime) as duration
from (select users, area, grp, min(entertime) as entertime, max(exittime) as exittime
      from block
      group by users, area, grp
    ) t2
order by 5;

Я внес некоторые изменения в " Сброс номера строки в соответствии с изменением данных записи", чтобы прийти к решению.

Другие вопросы по тегам