oracle - 从开始时间开始1小时数据间隔15分钟的数据聚合

时间:2017-04-06 05:56:34

标签: sql oracle

我必须从Oracle Table获取数据,其中我有一个名为periodstarttime的日期字段,我想在第00,15,30,45分钟只获取聚合数据(聚合必须在1小时内完成数据)在一天内以5分钟的间隔输入数据

例如,如果在我的表中我将periodstarttime作为

periodstarttime        data
05/04/2017 1:00:00      10
05/04/2017 1:05:00       1
05/04/2017 1:10:00       2
05/04/2017 1:15:00       3
05/04/2017 1:20:00       4
05/04/2017 1:25:00       5
05/04/2017 1:30:00 
and so on....

然后我希望我的结果看起来像:

periodstarttime         data with 1hr aggregation
05/04/2017 1:00:00      data with 1hr aggregation from 1.00 to 2.00
05/04/2017 1:15:00      data with 1hr aggregation from 1.15 to 2.15
05/04/2017 1:30:00      data with 1hr aggregation from 1.30 to 2.30
05/04/2017 1:45:00      data with 1hr aggregation from 1.45 to 2.45

3 个答案:

答案 0 :(得分:0)

查看分析函数的Windowing_clause

就像这样

select periodstarttime, 
   SUM(DATA) OVER (RANGE BETWEEN CURRENT ROW AND INTERVAL '1' HOUR FOLLOWING ORDER BY periodstarttime),
   'data with 1hr aggregation from '||FIRST_VALUE(periodstarttime) OVER (RANGE BETWEEN CURRENT ROW AND INTERVAL '1' HOUR FOLLOWING ORDER BY periodstarttime)
     ||' to '||LAST_VALUE(periodstarttime) OVER (RANGE BETWEEN CURRENT ROW AND INTERVAL '1' HOUR FOLLOWING ORDER BY periodstarttime)
FROM ...
WHERE EXTRACT(MINUTE FROM periodstarttime) IN (0,15,30,45)

答案 1 :(得分:0)

这是一种方法:

WITH your_table AS (SELECT to_date('05/04/2017 01:00:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 10 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:05:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 20 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:10:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 30 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:15:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 40 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:20:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 50 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:25:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 60 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:30:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 70 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:40:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 80 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 01:50:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 90 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 02:00:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 100 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 02:10:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 110 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 02:20:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 120 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 02:30:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 130 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 02:40:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 140 DATA FROM dual UNION ALL
                    SELECT to_date('05/04/2017 03:00:00', 'dd/mm/yyyy hh24:mi:ss') periodstarttime, 150 DATA FROM dual)
-- End of setting up data in your_table; you would not need the above since you already have a table with data in it
-- See the below SQL for the main statement:
SELECT DISTINCT TRUNC(periodstarttime, 'hh') + FLOOR((TRUNC(periodstarttime, 'mi') - TRUNC(periodstarttime, 'hh'))/(15/1440))*15/1440 periodstarttime,
       sum(DATA) OVER (ORDER BY TRUNC(periodstarttime, 'hh') + FLOOR((TRUNC(periodstarttime, 'mi') - TRUNC(periodstarttime, 'hh'))/(15/1440))*15/1440
                       RANGE BETWEEN 0 PRECEDING AND 60/1440 FOLLOWING) sum_over_next_hour
FROM   your_table
ORDER BY periodstarttime;

PERIODSTARTTIME  SUM_OVER_NEXT_HOUR
---------------- ------------------
05/04/2017 01:00                660
05/04/2017 01:15                850
05/04/2017 01:30                770
05/04/2017 01:45                690
05/04/2017 02:00                750
05/04/2017 02:15                540
05/04/2017 02:30                290
05/04/2017 03:00                150

这适用于:

  1. 找到期间开始时间,我们通过查找每个期间的分钟时间,将其除以15分钟,找到该平均值,然后将该新数字乘以15分钟。这将时间分为15分钟组。

  2. 现在我们知道这些团体,我们可以做累积总和。因为我们想要跨越一小时的值,我们需要在当前时段和当前时段+ 1小时之间进行范围。注:这是包含性的,因此02:00值将包含在01:00期间的累计总和中。如果您不想这样做,请更改范围,使其达到59分钟(这很好,因为我们的时间段现在是小时的0,15,30或45分钟)。

答案 2 :(得分:0)

您可以使用TRUNC()CASE截断到最近的15分钟间隔,然后使用带有窗口子句的分析函数来获取滚动窗口的总和:

SELECT DISTINCT
       periodstarttime,
       SUM( data ) OVER ( ORDER BY periodstarttime
                          RANGE BETWEEN INTERVAL '0' MINUTE PRECEDING
                                AND     INTERVAL '45' MINUTE FOLLOWING
                        )
         AS hour_total,
       'data with 1hr aggregation from '
         || TO_CHAR( periodstarttime, 'HH24:MI' )
         || ' to '
         || TO_CHAR( periodstarttime + INTERVAL '1' HOUR, 'HH24:MI' )
         AS range
FROM   (
  SELECT CASE
           WHEN periodstarttime < TRUNC( periodstarttime, 'HH24' ) + INTERVAL '15' MINUTE
           THEN TRUNC( periodstarttime, 'HH24' )
           WHEN periodstarttime < TRUNC( periodstarttime, 'HH24' ) + INTERVAL '30' MINUTE
           THEN TRUNC( periodstarttime, 'HH24' ) + INTERVAL '15' MINUTE
           WHEN periodstarttime < TRUNC( periodstarttime, 'HH24' ) + INTERVAL '45' MINUTE
           THEN TRUNC( periodstarttime, 'HH24' ) + INTERVAL '30' MINUTE
           ELSE TRUNC( periodstarttime, 'HH24' ) + INTERVAL '45' MINUTE
         END AS periodstarttime,
         data
  FROM   table_name
)
ORDER BY periodstarttime;