我正在使用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
我已经看到了一些PIVOT
和CROSS APPLY
函数,其中指定了列(本例中为月份)并且事先进行了硬编码。有没有一种简单的方法可以根据[Month]
中的值动态创建这些列名?
答案 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]'
而且,只是为了好玩......
Exec [prc-Pivot] 'Select *,Qtr=''Q''+concat(concat(DatePart(QQ,Month),''-''),Year(Month)) from #Temp','Emp','sum(Qty)[]','Qtr',null
存储过程
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