2013-10-30 58 views
1

我真的需要接受CTE的结果,并计算出数据组的累积值。TSQL-2008 SUM(X)OVER(PARTITION ... ORDER BY CLAUSE)

数据集是:

PERIOD FT GROUP DEPT VALUE 
1 Actual KINDER MATH 200 
2 Actual KINDER MATH 363 
3 Actual KINDER MATH 366 
1 Budget KINDER MATH 457 
2 Budget KINDER MATH 60 
3 Budget KINDER MATH 158 
1 Actual HIGHSCH ENGLISH 456 
2 Actual HIGHSCH ENGLISH 745 
3 Actual HIGHSCH ENGLISH 125 
1 Budget HIGHSCH ENGLISH 364 
2 Budget HIGHSCH ENGLISH 158 
3 Budget HIGHSCH ENGLISH 200 
6 Budget HIGHSCH ENGLISH 502 
7 Budget HIGHSCH ENGLISH 650 
1 Actual COLL ENGLISH 700 
2 Actual COLL ENGLISH 540 
3 Actual COLL ENGLISH 160 
1 Budget COLL ENGLISH 820 
2 Budget COLL ENGLISH 630 
3 Budget COLL ENGLISH 800 

我要的是一个包含累积性量为每FT,集团,系

所以基本上,我想它看起来像这样的附加列:

PERIOD FT GROUP DEPT VALUE ACC VALUE 
1 Actual KINDER MATH 200 200 
2 Actual KINDER MATH 363 563 
3 Actual KINDER MATH 366 929 
1 Budget KINDER MATH 457 457 
2 Budget KINDER MATH 60 517 
3 Budget KINDER MATH 158 675 
1 Actual HIGHSCH ENGLISH 456 456 
2 Actual HIGHSCH ENGLISH 745 1201  
3 Actual HIGHSCH ENGLISH 125 1326  
1 Budget HIGHSCH ENGLISH 364 364 
2 Budget HIGHSCH ENGLISH 158 522 
3 Budget HIGHSCH ENGLISH 200 722 
1 Budget HIGHSCH ENGLISH 502 502 
2 Budget HIGHSCH ENGLISH 650 1152  
3 Budget HIGHSCH ENGLISH 336 1488  
1 Actual COLL ENGLISH 700 700 
2 Actual COLL ENGLISH 540 1240  
3 Actual COLL ENGLISH 160 1400  
1 Budget COLL ENGLISH 820 820 
2 Budget COLL ENGLISH 630 1450  
3 Budget COLL ENGLISH 800 2250  

如果我是在2012年SQL,我会使用类似这样:

SELECT period 
    ,ft 
    ,group 
    ,dept 
    ,value 
    ,CASE 
     WHEN FT = 'Actual' THEN SUM(value) OVER (PARTITION BY dept, group, ft ORDER BY period) 
     ELSE value 
     END AS AccValue 
FROM myTable 

但是,我在2008年,不能使用这种方法,并难以对如何复制这些数据。

请任何人都可以帮忙吗?

+1

为什么你不能在2008年复制这个?自2005年以来,“OVER”已经出现了。 – Kermit

+0

不仅仅是“over”... over.PARTITION BY和ORDER BY合计。我试了一下,每次都在订单上出错。在网上查看它说它不是2008年的一个功能。 –

+1

@FreshPrinceOfSO - 总计运行总计等的ORDER BY'是2012+ –

回答

1

这应该工作。 (我将禁止的列名从“GROUP”更改为“GROUP_”)

with cte (PERIOD, FT, GROUP_, DEPT, VALUE, AccValue) as (select t1.PERIOD, t1.FT, t1.GROUP_, t1.DEPT, t1.VALUE, SUM(t2.VALUE) as AccValue 
          from   myTable t1 
          join myTable t2 on t1.PERIOD>= t2.PERIOD 
          and t1.FT = t2.FT 
          and t1.GROUP_ = t2.GROUP_   
          and t1.DEPT = t2.DEPT 
          group by t1.PERIOD, t1.FT, t1.GROUP_, t1.DEPT, t1.VALUE 
        ) 
           select PERIOD 
        ,FT 
        ,GROUP_ 
        ,DEPT 
        ,VALUE 
        ,CASE 
         WHEN FT = 'Actual' THEN AccValue 
         ELSE VALUE 
         END AS AccValue 
         from cte 
           order by GROUP_ desc, FT, PERIOD, DEPT desc, VALUE 
+0

谢谢。我试图运行这个,到目前为止我的数据集运行需要一分钟,所以我觉得它不会是一个可行的解决方案。 :(更高效的低成本方法的任何想法? –

+0

如果您可以使用临时表而不是CTE,并且在除VALUE之外的所有列上创建索引 – cadaver

+0

好吧,我明白如何创建临时表并尝试这样做。我不知道如何做你建议的另一半。 –

1

简单的INNER JOIN应该有效。除非我误解了你,你想要的是一个正在运行的总数,对吗?

本示例使用虚拟数据创建一个虚拟表,然后使用内部联接作为运行总数。从性能角度来看,公用表表达式可能更有效。但为了简单起见,内部加入我是优先的。

/* Dummy table */  

create table testing1 
(col1 int not null identity(1,1), 
col2 varchar(5), 
col3 int) 


insert into testing1 
values ('a', 10), ('a', 20), ('a', 30), ('b', 40), ('b', 50) 

/* Running total example */ 

SELECT a.col1 
      , a.col2 
      , a.col3 
      , SUM(b.col3) AS total 

FROM testing1 a INNER JOIN testing1 b 
    ON a.col1 >= b.col1 
    AND a.col2 = b.col2 

GROUP BY a.col1, a.col2, a.col3 
ORDER BY a.col1 



/* Edit to include Output */ 
col1 col2 col3 total 
1 a 10 10 
2 a 20 30 
3 a 30 60 
4 b 40 40 
5 b 50 90 
+0

甜...比我的评论更好;) –

+0

这没有奏效。你是否可以使用http://sqlfiddle.com显示你的输出,以防万一我错了x –

+1

再试一次。如果您复制并粘贴,则需要删除一个随机的“'”。我删除了它。另外,对于我的输出中时髦的列格式感到抱歉,但您可以看到它执行了一次总计。 – rwking