3

我正在使用 sql server 2008,我想交叉表这个表

Month   Affec   KPI     Total   KPI_%   Out     rep_in_10  ftm
Jan-11  30565   34623   42003   82.4    7380    7003       5024
Jan-12  20955   25915   27857   93      1942    4754       3518
Feb-11  27754   27757   36483   76.1    8726    5648       4189
Feb-12  19513   25188   26962   93.4    1774    5768       4185
Mar-11  22838   23758   29951   79.3    6193    4394       3282
Mar-12  18778   25098   26177   95.9    1079    5784       4105
Apr-11  20235   21950   25917   84.7    3967    3895       2967

            Jan-11  Jan-12  Feb-11  Feb-12  Mar-11  Apr-11
Affec       30565   
KPI         34623   
Total       42003   
KPI_%       82.4         
Out         7380    
rep_in_10   7003
4

3 回答 3

1

在我看来,你不应该这样做。您可以使用 PHP 或您正在使用的任何东西在表示层上轻松实现这一点。数据库是用来获取数据的,而不是用来很好地格式化它的。将 Mahmoud 的回答更多地视为概念证明。但是查询永远不会像您现在获取数据的查询一样快。维护可能是反对它的另一个论据。

于 2012-12-10T10:05:16.053 回答
0

像这样:

;WITH UNpivoted
AS
(
  SELECT MonthsValue, Value, month
  FROM (SELECT [Month], 
        CAST([Affec] AS VARCHAR(10)) Affec ,
        CAST([KPIprecent] AS VARCHAR(10)) KPIprecent,
        CAST([Total] AS VARCHAR(10)) Total, 
        CAST([KPI] AS VARCHAR(10)) KPI, 
        CAST([Out] AS VARCHAR(10)) [Out],
        CAST([rep_in_10] AS VARCHAR(10)) [rep_in_10], 
        CAST([ftm] AS VARCHAR(10)) ftm
        FROM table1
       ) t
  UNPIVOT
  (
    MonthsValue FOR Value IN([Affec], 
                             [KPIprecent], 
                             [Total], 
                             [KPI],        
                             [Out], 
                             [rep_in_10], 
                             [ftm])
  ) u
)
  SELECT
    value,
    [Jan-11], 
    [Jan-12], 
    [Feb-11], 
    [Feb-12],
    [Mar-11], 
    [Mar-12], 
    [Apr-11]
  FROM
  (
    SELECT monthsvalue, value, month
    FROM Unpivoted
  ) t
  PIVOT
  (MAX(monthsvalue) for Month IN ([Jan-11], 
                                 [Jan-12], 
                                 [Feb-11], 
                                 [Feb-12],
                                 [Mar-11], 
                                 [Mar-12], 
                                 [Apr-11])
  ) p;

SQL 小提琴演示

这会给你:

|      VALUE | JAN-11 | JAN-12 | FEB-11 | FEB-12 | MAR-11 | MAR-12 | APR-11 |
-----------------------------------------------------------------------------
|      Affec |  30565 |  20955 |  27754 |  19513 |  22838 |  18778 |  20235 |
|        ftm |   5024 |   3518 |   4189 |   4185 |   3282 |   4105 |   2967 |
|        KPI |   82.4 |   93.0 |   76.1 |   93.4 |   79.3 |   95.9 |   84.7 |
| KPIprecent |  34623 |  25915 |  27757 |  25188 |  23758 |  25098 |  21950 |
|        Out |   7380 |   1942 |   8726 |   1774 |   6193 |   1079 |   3967 |
|  rep_in_10 |   7003 |   4754 |   5648 |   5768 |   4394 |   5784 |   3895 |
|      Total |  42003 |  27857 |  36483 |  26962 |  29951 |  26177 |  25917 |
于 2012-12-10T09:58:14.737 回答
0

对于这种类型的数据转换,您将需要使用该UNPIVOT函数,然后PIVOT在 SQL Server 中应用该函数。

有两种方法可以执行此操作,或者使用静态版本对值进行硬编码,使用动态 sql 将值生成为运行时。

静态版本:

UNPIVOT部分从您的多个列中获取数据并将其转换为两行。请注意,使用 unpivot 要记住的一件事是数据类型必须相同。因此,您可能必须对数据执行数据类型转换。

select [Month], value, col
from
(
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [Affec], [KPI], [Total], [KPI_%], [Out], [rep_in_10], [ftm]
  from yourtable
) src
unpivot
(
  value
  for col in ([Affec], [KPI], [Total], [KPI_%], [Out], [rep_in_10], [ftm])
) unpiv

请参阅带有演示的 SQL Fiddle

结果:

|         MONTH | VALUE |       COL |
-------------------------------------
|  January-2011 | 30565 |     Affec |
|  January-2011 | 34623 |       KPI |
|  January-2011 | 42003 |     Total |
|  January-2011 |  82.4 |     KPI_% |
|  January-2011 |  7380 |       Out |  ---etc

然后您将其PIVOT应用于月份:

select *
from
(
  select [Month], value, col
  from
  (
    select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
      [Affec], [KPI], [Total], [KPI_%], [Out], [rep_in_10], [ftm]
    from yourtable
  ) src
  unpivot
  (
    value
    for col in ([Affec], [KPI], [Total], [KPI_%], [Out], [rep_in_10], [ftm])
  ) unpiv
) src
pivot
(
  max(value)
  for month in ([January-2011], [February-2011], [March-2011],
             [April-2011], [January-2012], [February-2012], [March-2012])
) piv

请参阅带有演示的 SQL Fiddle

结果:

|       COL | JANUARY-2011 | FEBRUARY-2011 | MARCH-2011 | APRIL-2011 | JANUARY-2012 | FEBRUARY-2012 | MARCH-2012 |
------------------------------------------------------------------------------------------------------------------
|     Affec |        30565 |         27754 |      22838 |      20235 |        20955 |         19513 |      18778 |
|       ftm |         5024 |          4189 |       3282 |       2967 |         3518 |          4185 |       4105 |
|       KPI |        34623 |         27757 |      23758 |      21950 |        25915 |         25188 |      25098 |
|     KPI_% |         82.4 |          76.1 |       79.3 |       84.7 |           93 |          93.4 |       95.9 |
|       Out |         7380 |          8726 |       6193 |       3967 |         1942 |          1774 |       1079 |
| rep_in_10 |         7003 |          5648 |       4394 |       3895 |         4754 |          5768 |       5784 |
|     Total |        42003 |         36483 |      29951 |      25917 |        27857 |         26962 |      26177 |

动态版本:

上面的方法很好用,如果你有一个已知数量的值,但你的值是未知的,那么你会想要使用动态 sql。我猜你会想要一个动态版本,因为你会有未知数量的日期:

DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @colsUnpivot = STUFF((SELECT DISTINCT ',' 
                      + quotename(c.name)
                    from sys.columns as C
                   where C.object_id = object_id('yourtable') and
                         C.name not in ('Month')
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @cols = STUFF((SELECT ',' + QUOTENAME(DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4))) 
                    from yourtable
                    group by [Month]
                    order by [Month]
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT col,' + @cols + ' from 
             (
               select [Month], value, col
              from
              (
                select DateName(month,[Month]) +''-''+Cast(datepart(year, [month]) as varchar(4)) Month,
                  [Affec], [KPI], [Total], [KPI_%], [Out], [rep_in_10], [ftm]
                from yourtable
              ) src
              unpivot
              (
                value
                for col in ('+@colsunpivot+')
              ) unpiv
            ) x
            pivot
            (
              max(value)
              for [Month] in (' + @cols + ')
            ) p '

execute(@query)

请参阅带有演示的 SQL Fiddle

结果将与动态版本相同。

UNION ALL/CASE 与聚合:

最后,如果您无权访问UNPIVOTorPIVOT函数,那么您可以使用 aUNION ALL来取消透视,并使用带有 a 的聚合函数CASE来透视数据:

select col,
  max(case when month='January-2011' then value end) [January-2011],
  max(case when month='February-2011' then value end) [February-2011],
  max(case when month='March-2011' then value end) [March-2011],
  max(case when month='April-2011' then value end) [April-2011],
  max(case when month='January-2012' then value end) [January-2012],
  max(case when month='February-2012' then value end) [February-2012],
  max(case when month='March-2012' then value end) [March-2012]
from
(
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [Affec] value,
    'Affec' col
  from yourtable
  union all
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [KPI] value,
    'KPI' col
  from yourtable
  union all
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [Total] value,
    'Total' col
  from yourtable
  union all
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [KPI_%] value,
    'KPI_%' col
  from yourtable
  union all
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [rep_in_10] value,
    'rep_in_10' col
  from yourtable
  union all
  select DateName(month,[Month]) +'-'+Cast(datepart(year, [month]) as varchar(4)) Month,
    [ftm] value,
    'ftm' col
  from yourtable
) src
group by col

请参阅带有演示的 SQL Fiddle

于 2012-12-10T10:07:21.690 回答