2017-07-27 162 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