Lot's of our sites are using database that for better or worse are starting to store data as metadata.
I'm not a particular fan because though generating the things that utilize this is easy, reporting against it is a whole other story. So I got into pivots.
So here's a simple example, of course this works great when you know the values in the table. But I'll show the starting point.
SELECT [January]
, [February]
, [March]
FROM ( SELECT [Month]
, SaleAmount
FROM Sales
) p PIVOT ( SUM(SaleAmount)
FOR [Month]
IN ([January],[February],[March])
) AS pvt
But I wanted to do something that worked on something dynamic:
I started here with Jeff Smith's excellent Dynamic SQL Crosstab Stored procedure
(don't loose this as this will work great with older SQL servers)
So I created this Stored Procedure using the new Pivot function in SQL server.
So in the case above you would do this
CREATE procedure [dbo].[GetPivot]
( @Select varchar(8000),
@PivotCol varchar(100),
@Summaries varchar(100),
@OtherCols varchar(8000) = Null)
AS
set nocount on
set ansi_warnings off
declare @Vals varchar(8000);
declare @sql varchar(8000);
declare @sqlView varchar(8000);
set @Vals = '';
set @OtherCols= isNull(@OtherCols + ',','')
set @sql = 'select distinct convert(varchar(100),' + @PivotCol + ') as TPivot FROM (' + @Select + ') A'
create table #temp (TPivot varchar(100))
insert into #temp
exec (@sql)
select @Vals = @Vals + ', [' + TPivot +']'
from #Temp
drop table #Temp
select @Vals = RIGHT ( @vals , len(@vals)-1)
set @SQLView = 'SELECT ' + @otherCols + @vals + ' FROM (' + @Select + ') up PIVOT (' + @Summaries + ' FOR ' + @PivotCol+ ' IN (' + @vals + ')) AS pvt'
--Print @SQLView
exec (@SQLView)
set nocount off
exec GetPivot
'SELECT [Month]
, SaleAmount
FROM Sales',
[Month],
'sum(SaleAmount)',
'Sales'
I wanted to throw in order by because our questions came in a particular sequence:
So here's one with order by:
CREATE procedure [dbo].[GetPivotWithOrder]
( @Select varchar(8000),
@PivotCol varchar(100),
@Summaries varchar(100),
@OtherCols varchar(100) = Null,
@OrderBy varchar(800) = Null)
AS
set nocount on
set ansi_warnings off
declare @Vals varchar(8000);
declare @sql varchar(8000);
declare @sqlView varchar(8000);
declare @OrderByText varchar(8000);
declare @SelectForPivot varchar(8000);
set @Vals = '';
set @OtherCols= isNull(@OtherCols + ',','')
set @OrderByText= isNull('Order By ' + @OrderBy,'')
set @SelectForPivot = replace(@Select, @OrderBy + ',','')
set @OrderBy= isNull(', ' + @OrderBy,'')
set @sql = 'select distinct convert(varchar(100),' + @PivotCol + ') as TPivot ' + @OrderBy + ' FROM (' + @Select + ' ) A ' + @OrderByText
Print @sql
create table #temp (TPivot varchar(100), orderBy int)
insert into #temp
exec (@sql)
select @Vals = @Vals + ', [' + TPivot +']'
from #Temp
order by orderBy
drop table #Temp
select @Vals = RIGHT ( @vals , len(@vals)-1)
set @SQLView = 'SELECT ' + @otherCols + @vals + ' FROM (' + @SelectForPivot + ') up PIVOT (' + @Summaries + ' FOR ' + @PivotCol+ ' IN (' + @vals + ')) AS pvt'
Print @SQLView
exec (@SQLView)
set nocount off
The commented out line --Print (@SQLView) will generate the actual pivot code from the dynamic information letting you create views or simple pivots
This has led to many quick solutions to difficult problems for a particular site and may lead to greater contributions in the future.
No comments:
Post a Comment