Oracle Соединение между интервалами минут - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть некоторые проблемы с объединением таблиц с различным интервалом дат по минутам.

Пример:

table1

ID  Modules    Timestamp
1   Delivered  02-FEB-2020 08:24:45
1   Read       02-FEB-2020 08:27:50
1   Delivered  03-FEB-2020 09:24:45
1   Read       03-FEB-2020 10:00:50
2   Delivered  03-FEB-2020 09:28:10
2   Read       03-FEB-2020 09:30:11

Вопрос:

is есть ли способ заставить данные стать такими?

 ID  Modules1    Timestamp1            Modules2   Timestamp2
 1   Delivered   02-FEB-2020 08:24:45  Read       02-FEB-2020 08:27:50
 1   Delivered   03-FEB-2020 09:24:45
 1   Read        03-FEB-2020 10:00:50
 2   Delivered   03-FEB-2020 09:28:10  Read       03-FEB-2020 09:30:11

Цель:

, поэтому, если кто-то прочитает в течение 5 минут, он присоединится, если не данные останутся прежними.

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

Я интерпретирую это как тип проблемы пробелов и островков. Каждый «остров» начинается с задержки в 5 минут для «Read» или любой строки с «Delivered».

with tgrp as (
      select t.*,
             sum(case when modules = 'Delivered' or
                           prev_timestamp < timestamp - interval '5' minute
                        then 1 else 0
                   end) over (partition by id order by timestamp) as grp
      from (select t.*,
                   lag(timestamp) over (partition by id order by timestamp) as prev_timestamp
            from t
           ) t
      )
select id,
       max(case when seqnum = 1 then module end) as module1,
       max(case when seqnum = 1 then timestamp end) as timestamp1,
       max(case when seqnum = 2 then module end) as module2,
       max(case when seqnum = 2 then timestamp end) as timestamp2
from (select tgrp.*,
             row_number() over (partition by id, grp order by timestamp) as seqnum
      from tgrp
     ) tgrp
group by id, grp;

EDIT:

Я думаю, что более простой способ - это поставить данные вместе, используя lead(), а затем фильтруйте и корректируйте окончательные значения:

select t.id, t.module, t.timestamp,
       (case when t.next_module = 'Read' and
                  t.next_timestamp < t.timestamp + interval '5' minute
             then t.next_module
        end) as module2,
       (case when t.next_module = 'Read' and
                  t.next_timestamp < t.timestamp + interval '5' minute
             then t.next_timestamp
        end) as timestamp2
from (select t.*,
             lead(module) over (partition by id order by timestamp) as next_module,
             lead(timestamp) over (partition by id order by timestamp) as next_timestamp
      from t
     ) t
where module = 'Delivery' or
      (next_timestamp > timestamp + interval '5' minute)
0 голосов
/ 04 февраля 2020

Вы можете самостоятельно объединиться для достижения желаемого результата следующим образом:

With cte as 
(Select t.*, 
       Row_number() over (partition by id, modules order by timestamp) as rn
  From your_table t)
Select t1.*, 
       case when t1.modules = 'delivered' and t1.timestamp + interval '5' minute <= t2.timestamp 
            then t2.timestamp 
       end as timestamp2
       From cte t1 
       left join cte t2
       On (t1.rn = t2.rn and t2.modules = 'read')
       Left join cte3 
       On (t1.rn = t3.rn and t3.modules = 'delivered')
Where t1.modules = 'delivered' or t3.timestamp + interval '5' minute > t2.timestamp

Cheers !!

...