with ds as
(select 1 id
,'dev' user_id
,'abc5' session_id
,'01.01.2017 08:00' logon_time
,'01.01.2017 09:00' logoff_time
from dual
union
select 2 id
,'sta' user_id
,'dg6h' session_id
,'01.01.2017 09:00' logon_time
,'01.01.2017 10:00' logoff_time
from dual
union
select 3 id
,'dev' user_id
,'sg2e' session_id
,'01.01.2017 08:30' logon_time
,'01.01.2017 09:00' logoff_time
from dual
union
select 4 id
,'dev' user_id
,'df4r' session_id
,'03.01.2017 08:30' logon_time
,'05.01.2017 09:00' logoff_time
from dual
union
select 5 id
,'sta' user_id
,'dg6h' session_id
,'04.01.2017 18:00' logon_time
,'05.01.2017 02:00' logoff_time
from dual
union
select 6 id
,'sta' user_id
,'sg8e' session_id
,'05.01.2017 08:30' logon_time
,'06.01.2017 09:00' logoff_time
from dual)
,
dt as
(select id
,user_id
,session_id
,to_date(logon_time, 'dd.mm.yyyy hh24:mi') logon_time
,to_date(logoff_time, 'dd.mm.yyyy hh24:mi') logoff_time
from ds)
,
mont as
(select trunc(to_date('12.01.2017', 'dd.mm.yyyy'), 'mm') + level - 1 d_date
from dual
connect by trunc(to_date('12.01.2017', 'dd.mm.yyyy'), 'mm') + level - 1 between
trunc(to_date('12.01.2017', 'dd.mm.yyyy'), 'mm') and last_day(to_date('12.01.2017', 'dd.mm.yyyy')))
,
dat as
(select dt.*
,m.*
,case
when trunc(dt.logon_time, 'dd') = m.d_date then
dt.logon_time
else
m.d_date
end s_date
,case
when trunc(dt.logoff_time, 'dd') = m.d_date then
dt.logoff_time
else
m.d_date + 1
end f_date
,(case
when trunc(dt.logoff_time, 'dd') = m.d_date then
dt.logoff_time
else
m.d_date + 1
end) - (case
when trunc(dt.logon_time, 'dd') = m.d_date then
dt.logon_time
else
m.d_date
end) diff_time
from dt
join mont m on m.d_date between trunc(dt.logon_time) and trunc(dt.logoff_time))
,
fin as
(select d_date
,user_id
,numtodsinterval(sum(diff_time), 'day') diff_time
,row_number() over(partition by d_date order by sum(diff_time) desc) rnum
from dat
group by d_date
,user_id)
select m.d_date
,f.user_id
,case
when f.diff_time is not null then
extract(day from f.diff_time) || ' ' || extract(hour from f.diff_time) || ':' ||
extract(minute from f.diff_time)
end ff
from mont m
left join fin f on f.d_date = m.d_date
and f.rnum = 1