2017-07-27 89 views
0

我有一个脚本:的Oracle SQL聚合功能

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分钟是输入,则间隔是每小时一次。

谢谢

回答

2

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

这两种解决方案工作,但我喜欢这一个多在桶中的主分割间隔。感谢您的努力! – sandman

2

这里是一个适合您的需求的方式:

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; 

的问题是,你说:

我想的时间间隔也能在短时间内进入了一个&变量。因此,如果60分钟是输入,则间隔是每小时一次。

问题是,如果你想要例如30分钟的时间间隔,那么在你的where子句中只需要最后30分钟,那么每个用户/ 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; 

希望这有助于

问候

+0

谢谢你的努力! – sandman