2016-11-15 31 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);