计算Oracle sql中时间段之间的数据平均值

时间:2016-11-24 20:59:33

标签: sql oracle oracle11g

我有下表名为IMETERDATA:

DEVNAME VARCHAR2(25)
DEVID   VARCHAR2(8)
USEDATE TIMESTAMP(6)
INSTANTPOWER    NUMBER(3,0)
TOTALENERGY NUMBER(7,4)
ROWNUMBER   NUMBER(4,0)

我想计算并显示2小时间隔的Totalenergy平均值。例如,如果我有特定日期的数据(例如2016年11月22日),我想计算Totalenergy的平均时间:上午12点至凌晨2点,凌晨2点至凌晨4点至晚上10点至晚上12点。我想计算具有指定间隔的所有日期的平均值。到目前为止我做了什么:

    select to_number(to_char(USEDATE, 'HH24')) as "HOUR", 
    avg(TOTALENERGY) as "AVERAGE", TRUNC(USEDATE, 'DD') as "DATE"
    from IMETERDATA 
    WHERE TRUNC(USEDATE) in (select DISTINCT(TRUNC(USEDATE, 'DD')) 
    from IMETERDATA) and (to_number(to_char(USEDATE, 'HH24')) >= 12 and to_number(to_char(USEDATE, 'HH24')) < 14 )
    group by to_number(to_char(USEDATE, 'HH24')), TRUNC(USEDATE, 'DD'); 

此查询仅提供从下午12点到下午2点的平均值。我如何计算24小时?我希望结果从早上12点到晚上11点59分,间隔为2小时:

12AM - 2AM ---> 58.50
2AM - 4AM ----> 60.35
   ...
10PM - 11.59PM --> 40.35

2 个答案:

答案 0 :(得分:1)

  

嗯。我可以不创建另一张桌子吗?

不确定。使用如下所示的查询(此示例生成2小时2小时):

ALTER SESSION SET NLS_DATE_FORMAT = 'yyyy-mm-dd hh24:mi'
;
SELECT date '2016-11-22' + NUMTODSINTERVAL( 2 * (level - 1), 'HOUR' ) as period_start
FROM dual
CONNECT BY LEVEL <= 2 * 12 ; -- 2 days of 12 "two hours" periods

PERIOD_START   
----------------
2016-11-22 00:00
2016-11-22 02:00
2016-11-22 04:00
2016-11-22 06:00
2016-11-22 08:00
2016-11-22 10:00
2016-11-22 12:00
2016-11-22 14:00
2016-11-22 16:00
2016-11-22 18:00
2016-11-22 20:00
2016-11-22 22:00
2016-11-23 00:00
2016-11-23 02:00
2016-11-23 04:00
2016-11-23 06:00
2016-11-23 08:00
2016-11-23 10:00
2016-11-23 12:00
2016-11-23 14:00
2016-11-23 16:00
2016-11-23 18:00
2016-11-23 20:00
2016-11-23 22:00

 24 rows selected 

然后将上述查询的结果加入到您的表中并计算平均值

SELECT x.PERIOD_START,
       AVG( i.TOTALENERGY )
FROM (
   the_above_query
) x
JOIN IMETERDATA i
ON i.USEDATE >= x.PERIOD_START AND i.USEDATE < x.PERIOD_START + interval '2' hour
GROUP BY x.PERIOD_START

答案 1 :(得分:0)

看看Analytic Functions: windowing_clause,您可以直接进行。

select USEDATE, 
    AVG(TOTALENERGY) OVER (ORDER BY USEDATE RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND INTERVAL '1' HOUR FOLLOWING) as AVERAGE,
    MIN(USEDATE) OVER (ORDER BY USEDATE RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND INTERVAL '1' HOUR FOLLOWING) as INTERVAL_START,
    MAXUSEDATE) OVER (ORDER BY USEDATE RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND INTERVAL '1' HOUR FOLLOWING) as INTERVAL_END
from IMETERDATA;

此查询为您提供每次+/- 1小时(即2小时)的所有平均值。 如果您只需要给定时间的时间,您可以使用

with t as 
   (select USEDATE, 
      AVG(TOTALENERGY) OVER (ORDER BY USEDATE RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND INTERVAL '1' HOUR FOLLOWING) as AVERAGE,
      MIN(USEDATE) OVER (ORDER BY USEDATE RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND INTERVAL '1' HOUR FOLLOWING) as INTERVAL_START,
      MAXUSEDATE) OVER (ORDER BY USEDATE RANGE BETWEEN INTERVAL '1' HOUR PRECEDING AND INTERVAL '1' HOUR FOLLOWING) as INTERVAL_END
    from IMETERDATA)
select *
from t
where USEDATE = TRUNC(USEDATE, 'HH')
   AND EXTRACT(HOUR FROM USEDATE) IN (1,3,5,7,...);

您也可以使用EXTRACT(HOUR FROM USEDATE) IN (1,3,5,7,...)

代替MOD(EXTRACT(HOUR FROM USEDATE), 1) = 1

也许这不是你想要的100%(你的问题在这方面不是那么清楚)但我认为你知道如何使用它。