2016-11-15 29 views
-1

我有一個名爲登錄Oracle表具有列名as_time和條目是時間戳(6)數據類型:你如何總結基於oracle的sql數據?

15-NOV-16 11.01.43.255000000 AM 

我需要計算的記錄數每15分鐘過去30 select語句天。

輸出需要是這樣的:

Time     Count 
11/01/2016 00:00:00 10 
11/01/2016 00:15:00 10 
11/01/2016 00:30:00 50 
11/01/2016 00:45:00 70 
11/01/2016 01:00:00 10 
11/01/2016 01:15:00 10 
11/01/2016 01:30:00 10 
11/01/2016 02:45:00 160 

有人可以與構建SQL查詢幫助嗎?

+0

你有日曆表或類似的東西? –

+0

@Prdp,表中有其他列,但最重要的是as_time,我只需要計算每15分鐘的記錄數。 – user1471980

+0

我沒有考慮這張桌子。你有其他有日期列表的表嗎? –

回答

0

一種方法是截斷到最接近的小時,然後分別處理分鐘:

select trunc(as_time, 'HH') as yyyymmddhh, 
     floor(extract(minute from as_time)/15)*15 as mm, 
     count(*) 
from t 
group by trunc(as_time, 'HH'), 
     floor(extract(minute from as_time) 
order by 1, 2; 

備註:

  • 如果您願意,您可以將分鐘數和小時數組合到時間戳列中。
  • 這隻會返回有數據的時間段。
  • 這不包括as_date > sysdate - interval '30' day
1

試試這個 - 輪時間戳到最近的15分鐘,然後總結:

WITH 
test_data (as_time) AS 
(SELECT 
    CAST(sysdate + (rownum/24/60) AS TIMESTAMP) 
    FROM 
    all_objects 
    WHERE rownum < 150 
) 
SELECT 
TO_CHAR(TO_DATE(date_hour||':'||mins_rounded_down,'YYYY/MM/DD HH24:MI'),'YYYY/MM/DD HH24:MI') rounded_date 
,COUNT(*) 
FROM 
(SELECT 
    as_time 
    ,TO_CHAR(as_time,'YYYY/MM/DD HH24:MI') date_time 
    ,TO_CHAR(as_time,'YYYY/MM/DD HH24')  date_hour 
    ,TO_CHAR(as_time,'MI')     real_mins 
    ,TO_CHAR(MOD(FLOOR(TO_NUMBER(TO_CHAR(as_time,'MI'))/15)*15,60),'FM00') mins_rounded_down 
    FROM 
    test_data 
) 
WHERE 1=1 
AND as_time > sysdate - 30 
GROUP BY 
date_hour 
,mins_rounded_down 
; 
+0

我假設你想要下降。如果你想四捨五入到最近的使用ROUND而不是FLOOR。如果你想整理使用CEIL –

1

考慮到你已經提取了日期的部分,除了分鐘和秒(例如使用to_char) - 所有剩下的基本上是處理分鐘。

如果TBL是「提取」後的數據集,你不關心解決日期作爲字符串(您可以使用to_date總是隱蔽吧),這裏是一個合適的SQL查詢:

select dt_without_mins||floor(to_char(dt, 'mi')/15) * 15, count(*) 
from tbl 
group by dt_without_mins||floor(to_char(dt, 'mi')/15); 
1

像這樣的東西應該工作。在子查詢中創建一個時間表,根據時間比較進行連接,並按/ count分組;連接是用於數據緻密化的左外連接(時間間隔沒有任何活動仍然包含在內,計數爲0)。

select t.time_from, coalesce(count(*), 0) as ct 
from (
     select trunc(sysdate) - 30 + (level-1)/(24*4), 
       trunc(sysdate) - 30 + level/(24*4) 
     from dual 
     connect by level <= 30*24*4 
     ) t 
     left outer join login l 
     on l.as_time >= t.time_from and l.as_time < t.time_to 
group by t.time_from 
order by t.time_from 
; 
0

一個更通用的方法,這是一個:

CREATE OR REPLACE FUNCTION MakeInterval(ts IN TIMESTAMP, roundInterval IN INTERVAL DAY TO SECOND) RETURN TIMESTAMP DETERMINISTIC IS 
    denom INTEGER; 
BEGIN 
    IF roundInterval >= INTERVAL '1' HOUR THEN 
     denom := EXTRACT(HOUR FROM roundInterval); 
     IF MOD(24, denom) <> 0 THEN 
      RAISE VALUE_ERROR; 
     END IF; 
     RETURN TRUNC(ts) + TRUNC(EXTRACT(HOUR FROM ts)/denom) * denom * INTERVAL '1' HOUR; 
    ELSIF roundInterval >= INTERVAL '1' MINUTE THEN 
     denom := EXTRACT(MINUTE FROM roundInterval); 
     IF MOD(60, denom) <> 0 THEN 
      RAISE VALUE_ERROR; 
     END IF; 
     RETURN TRUNC(ts, 'hh') + TRUNC(EXTRACT(MINUTE FROM ts)/denom) * denom * INTERVAL '1' MINUTE; 
    ELSE 
     denom := EXTRACT(SECOND FROM roundInterval);     
     IF MOD(60, denom) <> 0 THEN 
      RAISE VALUE_ERROR; 
     END IF; 
     RETURN TRUNC(ts, 'mi') + TRUNC(EXTRACT(SECOND FROM ts)/denom) * denom * INTERVAL '1' SECOND; 
    END IF; 
END MakeInterval; 



select 
    MakeInterval(as_time, INTERVAL '15' MINUTE) as time, 
    count(*) AS count 
from the_table 
where as_time > sysdate - 30 
group by MakeInterval(as_time, INTERVAL '15' MINUTE);