Oracle SQL 聚合功能

Oracle SQL aggregate functionality

我有一个脚本:

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

它的输出是这样的:

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

如何将其分解为 HOURLY 段,以便输出如下所示:

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 

我希望间隔是以分钟为单位输入的 & 变量。因此,如果输入 60 分钟,则间隔为每小时,例如。

谢谢

这是一个很好的挑战。我使用数字生成器生成最大和最小采样时间之间的序列。使用 &bucket_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

这里有一种方法可以满足您的需求:

select 
regexp_replace(b.username, '[0-9]', '') username, a.wait_class,
  to_char( round( ( a.sample_time - trunc( a.sample_time ) ) * (24*(60/&minutes)) )/ (24*(60/&&minutes)) + trunc( a.sample_time ), 'HH24:MI:SS' ) start_time, -- Used to round the time to the nearest XX minutes
  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, to_char( round( ( a.sample_time - trunc( a.sample_time ) ) * (24*(60/&minutes)) )/ (24*(60/&&minutes)) + trunc( a.sample_time ), 'HH24:MI:SS' )
order by 
  3 desc;

问题是你说:

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.

问题是,如果您想要例如 30 分钟的间隔,那么在您的 where 子句中您只需要最后 30 分钟,那么每个 user/wait_class.

将只有两行

所以你需要像这样添加第二个参数:

SELECT regexp_replace(b.username, '[0-9]', '') username,
  a.wait_class,
  to_char( round( ( cast(a.sample_time as date) - trunc( cast(a.sample_time as date) ) ) * (24*(60/
  &&minutes)) )                         / (24*(60/
  &&minutes))                          + TRUNC( CAST(a.sample_time AS DATE) ), 'HH24:MI:SS' ) start_time, -- Used to round the time to the nearest XX minutes
  COUNT(                                        *)
FROM v$active_session_history a,
  dba_users b
WHERE a.user_id  =b.user_id
and a.sample_time>sysdate -
  &&from_minutes                /1440
GROUP BY regexp_replace(b.username, '[0-9]', ''),
  a.wait_class,
  to_char( round( ( cast(a.sample_time as date) - trunc( cast(a.sample_time as date) ) ) * (24*(60/
  &&minutes)) )                         / (24*(60/
  &&minutes))                          + TRUNC( CAST(a.sample_time AS DATE) ), 'HH24:MI:SS' )
ORDER BY 3 DESC;

希望对您有所帮助

此致