存储过程 - 数据透视表,表变换拼图

时间:2013-04-15 14:43:37

标签: sql-server-2005 stored-procedures pivot

有人可以就如何将分配表格转换为目标表格提供一些帮助:

分配

SA    Project         From            TO        Allocation      Comment
-------------------------------------------------------------------------------
Bin     p1          2008-11-01     2008-11-30       0.3            a
Bin     p1          2008-12-01     2008-12-31       0.3            a
Bin     p1          2009-01-01     2009-01-31       0.3            a
Bin     p1          2012-09-01     2012-09-30       0.5            b
Bin     p1          2012-10-01     2012-10-31       0.5            b
Bin     p1          2012-11-01     2012-11-30       0.5            b
Bin     p1          2012-12-01     2012-12-31       0.5            b
Mike    p2          2011-09-01     2011-09-30       0.3            c
Mike    p2          2011-10-01     2011-10-31       0.3            c
Mike    p2          2011-11-01     2011-11-30       0.3            c
Mike    p2          2011-12-01     2011-12-31       0.3            c
Mike    p2          2012-01-01     2012-01-31       0.3            c
Mike    p2          2012-05-01     2012-05-31       0.6            c
Mike    p2          2012-06-01     2012-06-30       0.6            c
Mike    p2          2012-07-01     2012-07-31       0.6            c
Mike    p1          2011-10-01     2011-10-31       0.45           d
Mike    p1          2011-11-01     2011-11-30       0.45           d
Mike    p1          2011-12-01     2011-12-31       0.45           d
Mike    p1          2012-10-01     2012-10-31       0.32           d
Mike    p1          2012-11-01     2012-11-30       0.32           d
Mike    p1          2012-12-01     2012-12-31       0.32           d

=============================================== =================================

:定位

请注意,11月的12月份是去年1月2日... 10月份。

SA  Project Year  Nov  Dec  Jan Feb Mar Apr May  Jun  Jul  Aug  Sep  Oct Comment Total  
---------------------------------------------------------------------------------------
Bin   p1    2008  0.3  0.3  0.3  0   0   0   0    0    0    0    0    0     a     0.9
Bin   p1    2011   0    0    0   0   0   0   0    0    0    0   0.5  0.5    b      1
Bin   p1    2012  0.5  0.5   0   0   0   0   0    0    0    0    0    0     b      1

Total             0.8  0.8  0.3  0   0   0   0    0    0    0   0.5  0.5          2.9

Mike  p1    2010   0    0    0   0   0   0   0    0    0    0    0   0.45   d     0.45
Mike  p1    2011  0.45 0.45  0   0   0   0   0    0    0    0    0   0.32   d     1.22
Mike  p1    2012  0.32 0.32  0   0   0   0   0    0    0    0    0    0     d     0.64
Mike  p2    2010   0    0    0   0   0   0   0    0    0    0   0.3  0.3    c     0.6
Mike  p2    2011  0.3  0.3  0.3  0   0   0  0.6  0.6  0.6   0    0    0     c     2.7

Total             1.07 1.07 0.3  0   0   0  0.6  0.6  0.6   0   0.3  1.07         5.61

现在我可以获得当前表:

当前

我只能在同一年的1月2月到12月。从去年11月开始,不知道如何连续两年制作它们。

SA  Project Year   Jan Feb Mar Apr  May  Jun  Jul   Aug  Sep   Oct    Nov  Dec  Comment
----------------------------------------------------------------------------------------
Bin   p1    2008    0   0   0   0    0    0    0     0    0     0    0.30  0.30   a
Bin   p1    2009  0.30  0   0   0    0    0    0     0    0     0      0    0     a
Bin   p1    2012    0   0   0   0    0    0    0     0   0.50  0.50  0.50  0.50   b
Mike  p1    2011    0   0   0   0    0    0    0     0    0    0.45  0.45  0.45   d
Mike  p1    2012    0   0   0   0    0    0    0     0    0    0.32  0.32  0.32   d
Mike  p2    2011    0   0   0   0    0    0    0     0   0.30  0.30  0.30  0.30   c
Mike  p2    2012  0.30  0   0   0  0.60  0.60  0.60  0    0     0     0     0     c

关键问题是如何将当前表转换为目标表。在目标表中,例如2008年11月12月和2009年1月2月3月4月5月6月7月8月9月应显示在同一行中。此外,还要添加每列的总和以及每行的总和。

欢迎任何建议。

如果有人可以帮助我实现这一目标,我将非常感激。

提前解决问题。

1 个答案:

答案 0 :(得分:0)

这是完整的解决方案,您可以检查代码并在SQLFiddle Demo上进行检查,我将在代码下面做一个简短的解释。

<强> SQLFiddle Demo

;WITH 
CTE_Pivot AS 
(
    SELECT 
         SA
        ,Project
        ,CASE WHEN MONTH([FROM]) <11 THEN YEAR([FROM])-1 ELSE YEAR([From]) END AS YEAR
        ,CASE WHEN MONTH([FROM]) = 11 THEN Allocation ELSE 0 END AS Nov
        ,CASE WHEN MONTH([FROM]) = 12 THEN Allocation ELSE 0 END AS [Dec]
        ,CASE WHEN MONTH([FROM]) = 1 THEN Allocation ELSE 0 END AS Jan
        ,CASE WHEN MONTH([FROM]) = 2 THEN Allocation ELSE 0 END AS Feb
        ,CASE WHEN MONTH([FROM]) = 3 THEN Allocation ELSE 0 END AS Mar
        ,CASE WHEN MONTH([FROM]) = 4 THEN Allocation ELSE 0 END AS Apr
        ,CASE WHEN MONTH([FROM]) = 5 THEN Allocation ELSE 0 END AS May
        ,CASE WHEN MONTH([FROM]) = 6 THEN Allocation ELSE 0 END AS Jun
        ,CASE WHEN MONTH([FROM]) = 7 THEN Allocation ELSE 0 END AS Jul
        ,CASE WHEN MONTH([FROM]) = 8 THEN Allocation ELSE 0 END AS Aug
        ,CASE WHEN MONTH([FROM]) = 9 THEN Allocation ELSE 0 END AS Sep
        ,CASE WHEN MONTH([FROM]) = 10 THEN Allocation ELSE 0 END AS Oct
        ,Allocation
        ,Comment
    FROM dbo.Allocation
)
,CTE_Rollup AS 
(
    SELECT SA, Project, YEAR 
        ,SUM(Nov) AS Nov
        ,SUM(Dec) AS Dec
        ,SUM(Jan) AS Jan
        ,SUM(Feb) AS Feb
        ,SUM(Mar) AS Mar
        ,SUM(Apr) AS Apr
        ,SUM(May) AS May
        ,SUM(Jun) AS Jun
        ,SUM(Jul) AS Jul
        ,SUM(Aug) AS Aug
        ,SUM(Sep) AS Sep
        ,SUM(Oct) AS Oct
        ,MAX(Comment) AS Comment
        ,SUM(Allocation) AS Total
    FROM CTE_Pivot 
    GROUP BY SA, Project, YEAR WITH ROLLUP
)
SELECT  
     CASE WHEN YEAR IS NULL THEN 'Total' ELSE SA END AS SA
    ,CASE WHEN YEAR IS NULL THEN NULL ELSE Project END AS Project
    ,YEAR 
    ,Nov,Dec,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct
    ,CASE WHEN YEAR IS NULL THEN NULL ELSE Comment END AS Comment
    ,Total 
FROM CTE_Rollup
WHERE SA IS NOT NULL AND (YEAR IS NOT NULL OR YEAR IS NULL AND Project IS NULL) 

首先,CTE将转移您的数据并创建11月,12月等列。此处的数据仍未分组。每个原始行都有一个单独的行,其值仅在一个月内,而在其他行中为零。使用简单的CASE声明(月份+ 1,月份&lt; 11),可以实现明年1月至10月的月份。

第二个CTE正在对数据进行分组,并使用WITH ROLLUP提示创建小计。它只返回你想要的东西,只需要几个额外的行(每个SA的小计,项目组合,每个SA和总计)。

最终查询只是消除那些行并格式化几行和列以匹配您的目标表。

请注意,我手边没有SQL Server 2005来测试它,但我几乎肯定它应该可以正常工作

编辑:SQLFiddle for updated version with blank rows before and after totals