如何获得一个月的滚动年度总数

时间:2012-11-08 21:22:02

标签: sql oracle

我试图从一组数据中获得12个月的总计,这些数据提供给定月份和年份的分钟数。在许多情况下,我不会有一个月的记录。有没有办法显示丢失的月份,其值为零(0),然后将其翻转或不显示它们,但让查询在12个月范围内确认这一点。以下查询是我试图使用的,但它只是抓住了先前的记录,并没有考虑缺少的月份。下面的查询似乎与某些总数略有不同。非常感谢任何帮助。

    Select year
         , month
         , SUM(NVL(minutes, 0)) OVER (order by year,month rows between 11 preceding and current row) as total_minutes
    from
    (
    Select *  
    from test_table
    Order by year, month
    )
    Order by year desc , month desc

这是用于创建测试表和数据的sql。

    drop table test_table;
    create table test_table (
      month    number(2),
      year     number(4),
      minutes  number(4,2)
    );

    insert into test_table values ( 1, 2012, 3 );
    insert into test_table values ( 2, 2012, 3 );
    insert into test_table values ( 3, 2012, 3 );
    insert into test_table values ( 4, 2012, 4 );
    insert into test_table values ( 5, 2012, 5 );
    insert into test_table values ( 7, 2012, 5 );
    insert into test_table values ( 8, 2012, 5 );
    insert into test_table values ( 9, 2012, 5 );
    insert into test_table values (10, 2012, 4 );
    insert into test_table values (11, 2012, 3 );
    insert into test_table values (12, 2012, 3 );
    insert into test_table values ( 1, 2011, 3 );
    insert into test_table values ( 2, 2011, 3 );
    insert into test_table values ( 5, 2011, 5 );
    insert into test_table values ( 6, 2011, 5 );
    insert into test_table values ( 7, 2011, 5 );
    insert into test_table values ( 8, 2011, 5 );
    insert into test_table values ( 9, 2011, 5 );
    insert into test_table values (10, 2011, 4 );
    insert into test_table values (11, 2011, 3 );
    insert into test_table values (12, 2011, 3 );
    insert into test_table values ( 1, 2010, 3 );
    insert into test_table values ( 2, 2010, 3 );
    insert into test_table values ( 3, 2010, 3 );
    insert into test_table values ( 4, 2010, 4 );
    insert into test_table values ( 5, 2010, 4 );
    insert into test_table values ( 6, 2010, 5 );
    insert into test_table values ( 7, 2010, 5 );
    insert into test_table values (10, 2010, 4 );
    insert into test_table values (11, 2010, 4 );
    insert into test_table values (12, 2010, 3 );

    COMMIT;

2 个答案:

答案 0 :(得分:0)

要填补几个月的空白,partition outer join(Oracle 10g广告更高)用于以下查询,如果您确实需要查看这些零,否则您可以保留原始查询重写SUM功能为SUM(NVL(minutes, 0)) OVER (partition by year order by year,month) as total_minutes

SQL> with m_num as(
  2    select level as mn
  3     from dual
  4   connect by level <= 12
  5  )
  6  select year
  7       , mn
  8       , minutes
  9       , sum(minutes) over(partition by year order by year, mn) rt
 10   from ( select tt.Year
 11               , mn.mn
 12               , nvl(tt.minutes, 0)  minutes
 13           from test_table tt
 14           partition by (tt.year)
 15           right outer join m_num mn
 16             on (tt.month = mn.mn)
 17        )
 18  order by year desc, mn desc
 19  ;


YEAR1         MN    MINUTES         RT
----- ---------- ---------- ----------
 2012         12          3         43
 2012         11          3         40
 2012         10          4         37
 2012          9          5         33
 2012          8          5         28
 2012          7          5         23
 2012          6          0         18
 2012          5          5         18
 2012          4          4         13
 2012          3          3          9
 2012          2          3          6
 2012          1          3          3
 2011         12          3         41
 2011         11          3         38
 2011         10          4         35
 2011          9          5         31
 2011          8          5         26
 2011          7          5         21
 2011          6          5         16
 2011          5          5         11
 2011          4          0          6
 2011          3          0          6
 2011          2          3          6
 2011          1          3          3

答案 1 :(得分:0)

我确实使用了外连接,但这并没有给我提供我所需要的12个月滚动范围。我不得不使用Windowing Clause来获得正确的范围和数字。

    with m_num as(
      select level as mn
       from dual
     connect by level <= 12
    )
    select year
         , mn
         , minutes
         , sum(minutes) over(order by year,mn rows between 11 preceding and current row) rt
    from ( select tt.Year
                , mn.mn
                , nvl(tt.minutes, 0)  minutes
            from test_table tt
            partition by (tt.year)
            right outer join m_num mn
              on (tt.month = mn.mn)
         )
    order by year desc, mn desc;