动态地将不同的值转换为列标题(即月份)

时间:2016-07-05 19:56:02

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

我正在使用SQL Server 2008 R2,并且希望能够为我的数据集中每个不同日期(月份)动态创建一个列提供帮助,我可以按用户汇总每月的数量。例如,我的数据如下:

Emp     Month       QTY
-------------------------
John    3/1/2016    20
John    3/1/2016    30
John    4/1/2016    15
John    6/1/2016    40
Jim     2/1/2016    25
Jim     4/1/2016    28
Jim     5/1/2016    15
Jim     5/1/2016    15
Jim     6/1/2016    32
Alex    4/1/2016    20
Alex    4/1/2016    20
Alex    4/1/2016    20
Alex    5/1/2016    45

并且我希望每月获得Emp的总数,如下所示:

Employee    2/1/2016    3/1/2016    4/1/2016    5/1/2016    6/1/2016
--------------------------------------------------------------------
John        0           50          15          0           40
Jim         25          0           28          30          32
Alex        0           0           60          45          0

我已经看到了一些PIVOTCROSS APPLY函数,其中指定了列(本例中为月份)并且事先进行了硬编码。有没有一种简单的方法可以根据[Month]中的值动态创建这些列名?

无论哪种方式,任何帮助都非常感谢。

1 个答案:

答案 0 :(得分:0)

PIVOT非常好,但是我使用了一个存储过程来处理大量的Dynamic Pivots。

源可以是table,view,#temp,甚至是sql

请注意,您可以定义其他聚合(即Total,Min,Max,Avg,STD ......)。您还可以定义其他分组依据

Exec [prc-Pivot] '#Temp','Month','sum(Qty)[]','Emp','count(*)[Records],sum(Qty)[Total],min(Qty)[Min],max(Qty)[Max],Avg(Qty)[Avg]'

返回 enter image description here

而且,只是为了好玩......

Exec [prc-Pivot] 'Select *,Qtr=''Q''+concat(concat(DatePart(QQ,Month),''-''),Year(Month)) from #Temp','Emp','sum(Qty)[]','Qtr',null

enter image description here

存储过程

CREATE PROCEDURE [dbo].[prc-Pivot] (
    @Source varchar(1000),          -- Any Table or Select Statement
    @PvotCol varchar(250),          -- Field name or expression ie. Month(Date)
    @Summaries varchar(250),        -- aggfunction(aggValue)[optionalTitle]
    @GroupBy varchar(250),          -- Optional additional Group By 
    @OtherCols varchar(500) )       -- Optional Group By or aggregates
AS

--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]'


Set NoCount On
Set Ansi_Warnings Off

Declare @Vals varchar(max),@SQL varchar(max);
Set @Vals = ''
Set @OtherCols= IsNull(', ' + @OtherCols,'')
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '+@Source end
Create Table #TempPvot  (Pvot varchar(100))
Insert Into #TempPvot
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A')
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot +  ''' THEN '),')[', ' END),0) As [' + Pvot ) From #TempPvot Order by Pvot
Drop Table #TempPvot
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ')
--Print @SQL
Exec (@SQL)


Set NoCount Off
Set Ansi_Warnings on