按月和按季度对值进行分组

时间:2013-06-13 15:04:01

标签: sql-server sql-server-2008-r2

我有像

这样的数据

MyTable的

person   datetimeField   datavalue1
 a        20110104        3
 a2       20110105        2 
 b        20110302        5
 c        20110403        6
 d        20110605        2

最终结果应如下所示:(顺序并不重要)

 DatePart    SumDatavalue1
 January      5
 March        5
 April        6
 June         2
 Quarter1     10
 Quarter2     8

我能想到的唯一方法是使用两个单独的SELECT语句和GROUP BY,然后再使用UNION ALL。有更有效的方法吗?

编辑:我应该说可能有另一个列datavalue2,需要进行平均,而不是求和。不确定这是否有所作为。

2 个答案:

答案 0 :(得分:4)

是的,你可以做到。这就是设计用于grouping sets的内容。以下是执行所需操作的SQL示例:

select (case when datename(mm, dt) is null
             then qtr
             else datename(mm, dt)
        end), count(*), sum(val)
from (select t.*,
             'Quarter'+cast(datepart(qq, dt) as varchar(255)) as qtr
      from temp t
     ) t
group by grouping sets((datename(mm, dt)),
                       (qtr))
order by (case when qtr is null then 0 else 1 end),
         min(dt)

SQLFiddle是here

在回复您的评论时,grouping setsrollup(和cube)的概括。使用grouping sets,您可以像这样添加总数:

select (case when datename(mm, dt) is null and qtr is null
             then 'Total'
             when datename(mm, dt) is null
             then qtr
             else datename(mm, dt)
        end), count(*), sum(val)
from (select t.*,
             'Quarter'+cast(datepart(qq, dt) as varchar(255)) as qtr
      from temp t
     ) t
group by grouping sets((datename(mm, dt)),
                       (qtr),
                       ())
order by (case when qtr is null and datename(mm, dt) is null then 2
               when datename(mm, dt) is null then 1
               else 0
          end),
         min(dt)

主要的复杂因素是在第一列中打印出正确的值并获得正确的排序。

答案 1 :(得分:2)

对SubTotals使用ROLLUP ...它的效率很高,因为它只通过一次详细数据而不像2个独立的GroupBys

 SELECT CASE WHEN [DATEPART] IS NULL THEN 'Quarter' + CONVERT(VARCHAR(10),QQ)
             ELSE [DATEPART] END [DatePart], [SumDataValue1] 
 FROM  (
         SELECT DATENAME(mm, dateTimefield ) [DATEPART],DATENAME(qq, dateTimefield ) [QQ] , SUM(datavalue1) [SumDataValue1] 
         FROM MyTable
         GROUP BY DATENAME(qq, dateTimefield ), DATENAME(mm, dateTimefield ) WITH ROLLUP )A
 WHERE ( [DATEPART] IS NOT NULL OR QQ IS NOT NULL )

如果您正在寻找,请告诉我。