Search code examples
sqloracleaggregatedate-arithmetic

Oracle SQL aggregate functionality


I have a script:

select 
  regexp_replace(b.username, '[0-9]', '') username, a.wait_class, count(*)
from 
  v$active_session_history a, dba_users b
where 
  a.user_id=b.user_id and
  a.sample_time>sysdate - &minutes/1440
group by 
  regexp_replace(b.username, '[0-9]', ''), a.wait_class
order by 
  3 desc

and its output is something like:

USERNAME         WAIT_CLASS      COUNT(*) 
UMESS            Commit               139 
VITPOINT         User I/O             126 
VITPOINT         <NULL>                69 

How do I break it down into HOURLY segments, so that the output looks like:

USERNAME         START TIME   WAIT_CLASS      COUNT(*) 
UMESS            10:00:00     Commit               66 
UMESS            11:00:00     Commit               73
VITPOINT         10:00:00     User I/O             62
VITPOINT         11:00:00     User I/O             64
etc 

I would like the interval to be an & variable entered in minutes. So if 60 minutes is the input, then the interval is hourly, for example.

thank you


Solution

  • That has been a nice challenge. I used a number generator to generate a sequence between the max and min sample time. Use the &bucket_minutes variable to provide your interval in minutes.

    with cte_basedata as (
        select regexp_replace(u.username, '[0-9]', '') username, ash.wait_class, ash.sample_time
        from v$active_session_history ash
        join dba_users u on (ash.user_id = u.user_id)  
        where ash.sample_time>sysdate - &minutes/1440
    ), cte_ng as (
        select (sysdate - (level-1) / 24 / 60 * &bucket_minutes) bucket_end, (sysdate - (level) / 24 / 60 * &bucket_minutes) bucket_start
        from dual
        connect by level <= (select extract (day from (max(sample_time) - min(sample_time)) * 24 * 60) / &bucket_minutes + 1 from cte_basedata)
    ), cte_data as (
        select d.*, cte_ng.bucket_start
        from cte_basedata d
        left outer join cte_ng on (d.sample_time between cte_ng.bucket_start and cte_ng.bucket_end)
    )
    select username, wait_class, bucket_start, count(*) from cte_data
    group by username, wait_class, bucket_start