2015-10-21 106 views
1

我需要将每日表格动态地汇总为每周和每月。使用SQL汇总每周每月数据

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; 
+0

SELECT CAST(MIN([HRDATE])AS VARCHAR(20))+” TO '+ CAST(MAX([HRDATE])AS VARCHAR(20))作为HRDATE, SUM(STVAL),扇区,区域 FROM DAILY_TABLE。我是新来的sql。 GROUP BY HRDATE HAVING COUNT(DISTINCT [HRDATE])= 7 –

+0

您是否需要纯粹的SQL解决方案或PL/SQL过程? – diziaq

+0

pl sql程序 –

回答

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; 
/
+0

我很努力地使用next_day或last_day或dateadd。任何选择? –

+0

@jo_develop,我不明白为什么你不能在Oracle下工作时使用它们。 – diziaq

+0

这将工作。但是我们能否扩展这一逻辑,以便我可以每天运行每周和每月的汇总? –

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 | 
+0

这在某些情况下不起作用。假设区域为“空”,那么它不考虑该行。它也必须汇总。 –

+0

它是如何“不工作”?我刚刚使用'NULL'值更新了SQLFIDDLE,它正在聚合它们 - 如果你想要一个不同的行为,那么你将不得不更好地描述你的问题(并将它作为一个新问题)。 – MT0