对于这种类型的数据转换,您将需要使用该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 与聚合:
最后,如果您无权访问UNPIVOT
orPIVOT
函数,那么您可以使用 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