定期汇总数据

时间:2017-10-23 10:54:03

标签: sql oracle

我有一个表,其中包含不定期间隔数天的事务(金额列)和相关的时间戳(valuedatetime列)。我需要构建一个查询,该查询从开始到每天结束的常规时间间隔计算累积总和(例如每5分钟)。我们的想法是创建一个可用于构建每日线图的数据集。 我对此很新,任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( amount, valuedatetime ) AS
  SELECT  1, TIMESTAMP '2017-10-22 23:45:21.234' FROM DUAL UNION ALL
  SELECT  2, TIMESTAMP '2017-10-22 23:47:10.000' FROM DUAL UNION ALL
  SELECT  3, TIMESTAMP '2017-10-22 23:52:41.123' FROM DUAL UNION ALL
  SELECT  4, TIMESTAMP '2017-10-22 23:55:23.456' FROM DUAL UNION ALL
  SELECT  5, TIMESTAMP '2017-10-22 23:58:24.789' FROM DUAL UNION ALL
  SELECT  6, TIMESTAMP '2017-10-22 23:59:59.999' FROM DUAL UNION ALL
  SELECT  7, TIMESTAMP '2017-10-23 00:00:00.000' FROM DUAL UNION ALL
  SELECT  8, TIMESTAMP '2017-10-23 00:01:02.234' FROM DUAL UNION ALL
  SELECT  9, TIMESTAMP '2017-10-23 00:05:00.000' FROM DUAL UNION ALL
  SELECT 10, TIMESTAMP '2017-10-23 00:09:59.999' FROM DUAL;

查询1

SELECT SUM( amount ),
       --channel_id,
       TRUNC( valuedatetime )
       +
       TRUNC(
         (
           CAST( valuedatetime AS DATE ) - TRUNC( valuedatetime )
         )
         * 24 -- Hours per day
         * 60 -- Minutes per hour
         / 5  -- group into 5 minute buckets
       ) * 5 / 60 / 24 AS range_start
FROM   table_name
GROUP BY
       --channel_id,
       TRUNC( valuedatetime ),
       TRUNC(
         (
           CAST( valuedatetime AS DATE ) - TRUNC( valuedatetime )
         )
         * 24 -- Hours per day
         * 60 -- Minutes per hour
         / 5  -- group into 5 minute buckets
       )

<强> Results

| SUM(AMOUNT) |          RANGE_START |
|-------------|----------------------|
|           3 | 2017-10-22T23:45:00Z |
|           3 | 2017-10-22T23:50:00Z |
|          15 | 2017-10-23T00:00:00Z |
|          15 | 2017-10-22T23:55:00Z |
|          19 | 2017-10-23T00:05:00Z |

如果您想要包含没有条目的期间:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE table_name ( amount, valuedatetime ) AS
  SELECT  1, TIMESTAMP '2017-10-22 23:45:21.234' FROM DUAL UNION ALL
  SELECT  2, TIMESTAMP '2017-10-22 23:47:10.000' FROM DUAL UNION ALL
  SELECT  3, TIMESTAMP '2017-10-22 23:52:41.123' FROM DUAL UNION ALL
  SELECT  4, TIMESTAMP '2017-10-22 23:55:23.456' FROM DUAL UNION ALL
  SELECT  5, TIMESTAMP '2017-10-22 23:58:24.789' FROM DUAL UNION ALL
  SELECT  6, TIMESTAMP '2017-10-22 23:59:59.999' FROM DUAL UNION ALL
  SELECT  7, TIMESTAMP '2017-10-23 00:00:00.000' FROM DUAL UNION ALL
  SELECT  8, TIMESTAMP '2017-10-23 00:01:02.234' FROM DUAL UNION ALL
  SELECT  9, TIMESTAMP '2017-10-23 00:15:00.000' FROM DUAL UNION ALL
  SELECT 10, TIMESTAMP '2017-10-23 00:19:59.999' FROM DUAL;

查询1

WITH ranges ( dt ) AS (
  SELECT min_dt + NUMTODSINTERVAL( 5 * ( LEVEL - 1 ), 'MINUTE' )
  FROM   (
    SELECT TRUNC( CAST( MIN( valuedatetime ) AS DATE ) )
           +
           TRUNC(
             ( CAST( MIN( valuedatetime ) AS DATE )
             - TRUNC( MIN( valuedatetime ) ) )
             * 24 * 60 / 5
           ) * 5 / 60 / 24 AS min_dt,
           MAX( valuedatetime ) AS max_dt
    FROM   table_name
  )
  CONNECT BY
         min_dt + INTERVAL '5' MINUTE * ( LEVEL - 1 ) <= max_dt
)
SELECT COALESCE( SUM( amount ), 0 ) AS total_amount,
       --channel_id,
       r.dt AS range_start
FROM   ranges r
       LEFT OUTER JOIN table_name t
       ON ( r.dt               <= t.valuedatetime
           AND t.valuedatetime <  r.dt + INTERVAL '5' MINUTE )
GROUP BY
       --channel_id,
       r.dt
ORDER BY
       --channel_id,
       r.dt

<强> Results

| TOTAL_AMOUNT |          RANGE_START |
|--------------|----------------------|
|            3 | 2017-10-22T23:45:00Z |
|            3 | 2017-10-22T23:50:00Z |
|           15 | 2017-10-22T23:55:00Z |
|           15 | 2017-10-23T00:00:00Z |
|            0 | 2017-10-23T00:05:00Z |
|            0 | 2017-10-23T00:10:00Z |
|           19 | 2017-10-23T00:15:00Z |