SQLQuery для учета времени и времени ожидания в Oracle - PullRequest
0 голосов
/ 18 мая 2019

У меня есть таблица в oracle с приведенным ниже примером вывода.

EID   | type  |   Date
24    |  IN   |03/25/2019 6:45 am
24    |  OUT  |03/25/2019 8:05 am
24    |  IN   |03/25/2019 8:06 am
24    |  IN   |03/25/2019 8:28 am
24    |  OUT  |03/25/2019 9:48 am
24    |  IN   |03/25/2019 9:52 am
24    |  IN   |03/25/2019 9:57 am
24    |  IN   |03/25/2019 10:44 am
24    |  OUT  |03/25/2019 12:16 pm
24    |  OUT  |03/25/2019 1:00 pm
24    |  IN   |03/25/2019 1:05 pm
24    |  OUT  |03/25/2019 2:21  pm

Я хочу построить запрос для достижения следующих результатов:

EID |       TIMEIN        |    TIMEOUT            | DIIF_IN_MIN 
24  | 03/25/2019 6:45 am  | 03/25/2019 8:05 am    |   1 
24  | 03/25/2019 8:06 am  |       null            |   0
24  | 03/25/2019 8:28 am  | 03/25/2019 9:48 am    |   4
24  | 03/25/2019 9:52 am  |       null            |   0
24  | 03/25/2019 9:57 am  |       null            |   0
24  | 03/25/2019 10:44 am | 03/25/2019 12:16 pm   |   0
24  |        null         | 03/25/2019 1:00 pm    |   5
24  | 03/25/2019 1:05 pm  | 03/25/2019 2:21  pm   |   0

Ответы [ 2 ]

2 голосов
/ 19 мая 2019

Это можно сделать с помощью следующей логики.

Вы можете получить все in с помощью запроса lead().Затем вы можете получить непревзойденные значения out s, используя lag():

select t.eid, date as timein,
       (case when next_type = 'OUT' then next_date end) as timeout,
       ((case when next_type = 'OUT' then next_date end) - date) * (24 * 60) as diff_in_minutes
from (select t.*,
             lead(type) over (partition by eid order by date) as next_type,
             lead(type) over (partition by eid order by date) as next_date
      from t
     ) t
where type = 'IN'
union all
select t.eid, null as timein,
       date as timeout, null as diff_in_minutes
from (select t.*,
             lag(type) over (partition by eid order by date) as prev_type,
             lag(date) over (partition by eid order by date) as prev_date
      from t
     ) t
where type = 'OUT' and (prev_type <> 'IN' or prev_type is null);

Здесь - это скрипта db <> со всеми вашими данными, показывающая, что она поддерживает несколько входови OUTs.

Обратите внимание, что предполагается, что столбец даты / времени действительно равен date.Он преобразуется только в timestamp для отображения компонента времени в наборе результатов.

1 голос
/ 18 мая 2019

Вы можете использовать такую ​​логику с помощью аналитической функции окна вывода

with tab(eid, type, dates ) as
(
 select 24,'IN' ,timestamp'2019-03-25 06:45:00' from dual union all
 select 24,'OUT',timestamp'2019-03-25 08:05:00' from dual union all
 select 24,'IN' ,timestamp'2019-03-25 08:06:00' from dual union all
 select 24,'IN' ,timestamp'2019-03-25 08:28:00' from dual union all
 select 24,'OUT',timestamp'2019-03-25 09:48:00' from dual union all
 select 24,'IN' ,timestamp'2019-03-25 09:52:00' from dual    
)
select t1.eid, t1.dates as timein, t2.dates as timeout, 
       nvl(to_number(regexp_substr(to_char(t1.ld_dates - t2.dates),'[^:]+',1,2)),0) 
           as diff_in_minutes
  from ( select lead(dates) over (order by dates) as ld_dates, t.* 
           from tab t 
          where type = 'IN' order by dates) t1
  full join ( select * from tab where type = 'OUT' order by dates) t2
    on t1.dates <= t2.dates and ld_dates > t2.dates
 order by t1.dates;

EID TIMEIN              TIMEOUT             DIFF_IN_MINUTES
24  25.03.2019 06:45:00 25.03.2019 08:05:00 1
24  25.03.2019 08:06:00 NULL                0
24  25.03.2019 08:28:00 25.03.2019 09:48:00 4
24  25.03.2019 09:52:00 NULL                0

Демо

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