https://pastein.ru/t/27

  скопируйте уникальную ссылку для отправки


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