使用SQL汇总每周每月数据

时间:2015-10-21 10:12:09

标签: sql oracle union

我需要动态地将每日表汇总为每周和每月。

DAILY_TABLE:

----------------------------------------------
 SECTOR | AREA | STVAL |        HRDATE
----------------------------------------------
   USJ  |  TD  |   8   | 17-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 17-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 18-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 18-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 19-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 19-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 20-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 20-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 21-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 21-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 22-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 22-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 23-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 23-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 24-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 24-OCT-2015 00:00:00
   USJ  |  TD  |   8   | 25-OCT-2015 00:00:00
   USJ  |  TJ  |   4   | 25-OCT-2015 00:00:00

WEEKLY_TABLE:

----------------------------------------------
 SECTOR | AREA | STVAL |        HRDATE
----------------------------------------------
   USJ  |  TD  |  16   | 18-OCT-2015 00:00:00
   USJ  |  TJ  |   8   | 18-OCT-2015 00:00:00
   USJ  |  TD  |  56   | 25-OCT-2015 00:00:00
   USJ  |  TJ  |  28   | 25-OCT-2015 00:00:00

MONTHLY_TABLE:

----------------------------------------------
 SECTOR | AREA | STVAL |        HRDATE
----------------------------------------------
   USJ  |  TD  |   72  | 25-OCT-2015 00:00:00
   USJ  |  TJ  |   36  | 25-OCT-2015 00:00:00

假设这个程序本周没有运行,但是在下周运行,它必须聚合早期的一周和当前周数据。

编辑1:

SELECT CAST( MIN([HRDATE]) AS VARCHAR(20))
       +' TO '
       + CAST( MAX([HRDATE]) AS VARCHAR(20)) AS HRDATE,
       SUM(STVAL),
       SECTOR,
       AREA 
  FROM DAILY_TABLE
 GROUP BY HRDATE
HAVING COUNT(DISTINCT[HRDATE]) = 7;

2 个答案:

答案 0 :(得分:0)

这是分别进行每周和每月会计的两个程序。它们是相似的,仅在表格名称和“一个时期的最后一天”的计算方面有所不同。

CREATE OR REPLACE PROCEDURE make_week_accounting IS
  l_last_date DATE;
  -- the day you want to be the last in the week >> 1=SUNDAY, 2=MONDAY and so on
  c_week_end_day  CONSTANT NUMBER := 1; 
  c_long_time_ago CONSTANT DATE := DATE '1900-01-01';
BEGIN

 SELECT nvl(MAX(hrdate), c_long_time_ago) INTO l_last_date FROM weekly_table;

 INSERT INTO weekly_table(sector, area, stval, hrdate)
 SELECT sector, area, SUM(stval), month_end
   FROM (
          SELECT sector, area, stval, trunc(next_day(hrdate, c_week_end_day)) AS week_end
            FROM daily_table
           WHERE hrdate > l_last_date
        ) 
  GROUP BY sector, area, week_end;

END;
/

CREATE OR REPLACE PROCEDURE make_month_accounting IS
  c_long_time_ago CONSTANT DATE := DATE '1900-01-01';
BEGIN

 SELECT nvl(MAX(hrdate), c_long_time_ago) INTO l_last_date FROM monthly_table;

 INSERT INTO monthly_table(sector, area, stval, hrdate)
 SELECT sector, area, SUM(stval), month_end
   FROM (
          SELECT sector, area, stval, trunc(last_day(hrdate)) AS month_end
            FROM daily_table
           WHERE hrdate > l_last_date
        ) 
  GROUP BY sector, area, month_end;

END;
/

答案 1 :(得分:0)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE DAILY_TABLE ( SECTOR,AREA,STVAL,HRDATE ) AS
          SELECT 'USJ', 'TD', 8, DATE '2015-10-17' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-17' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-18' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-18' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-19' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-19' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-20' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-20' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-21' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-21' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-22' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-22' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-23' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-23' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-24' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-24' FROM DUAL
UNION ALL SELECT 'USJ', NULL, 4, DATE '2015-10-24' FROM DUAL
UNION ALL SELECT 'USJ', 'TD', 8, DATE '2015-10-25' FROM DUAL
UNION ALL SELECT 'USJ', 'TJ', 4, DATE '2015-10-25' FROM DUAL
UNION ALL SELECT 'USJ', NULL, 4, DATE '2015-10-25' FROM DUAL

查询1

SELECT SECTOR,
       AREA,
       SUM(STVAL) AS STVAL,
       TRUNC(HRDATE,'IW') AS HRDATE
FROM   DAILY_TABLE
GROUP BY 
       SECTOR,
       AREA,
       TRUNC(HRDATE,'IW')

<强> Results

| SECTOR |   AREA | STVAL |                    HRDATE |
|--------|--------|-------|---------------------------|
|    USJ | (null) |     8 | October, 19 2015 00:00:00 |
|    USJ |     TD |    16 | October, 12 2015 00:00:00 |
|    USJ |     TJ |     8 | October, 12 2015 00:00:00 |
|    USJ |     TD |    56 | October, 19 2015 00:00:00 |
|    USJ |     TJ |    28 | October, 19 2015 00:00:00 |

查询2

SELECT SECTOR,
       AREA,
       SUM(STVAL) AS STVAL,
       TRUNC(HRDATE,'MM') AS HRDATE
FROM   DAILY_TABLE
GROUP BY 
       SECTOR,
       AREA,
       TRUNC(HRDATE,'MM')

<强> Results

| SECTOR |   AREA | STVAL |                    HRDATE |
|--------|--------|-------|---------------------------|
|    USJ |     TJ |    36 | October, 01 2015 00:00:00 |
|    USJ | (null) |     8 | October, 01 2015 00:00:00 |
|    USJ |     TD |    72 | October, 01 2015 00:00:00 |