Technical Article

Dynamic pivoting

,

--create table master.dbo.Invoice([Department] varchar(50), [Year] int, [Month] int, Amount int);

exec dbo.dynamicPivot

@tablename = '[master].[dbo].[Invoice]',

@pivotColumn = '[month]',

@groupBy = '[Department],[Year]',

@aggregateColumns = '[Amount]',

@aggregation = 'SUM([Amount])',

@execute = 1;

go

Running this results in the below:

--sample data
set nocount on;
drop table  master.dbo.Invoice
go
create table  master.dbo.Invoice([Department] varchar(50), [Year] int, [Month] int, Amount int);
go
declare @y int = 2010,@m int = 1, @dp int = 1;
while @y <= 2014
begin;
set @m = 1;
while @m <= 12
begin;
if @m <= 3
set @dp = 1;
else if @m <= 6
set @dp = 2;
else if @m <= 12
set @dp = 3; 
insert into  master.dbo.Invoice
values
('Department '+cast(@dp as varchar(2)), @y,@m,(@y*@m)/10);
set @m = @m+1;
end;
set @y = @y+1;
end;
go
select * from master.dbo.Invoice
go
--run as sql script
declare
@tablename varchar(250) = '[master].[dbo].[Invoice]',
@pivotColumn varchar(250) = '[month]',
@groupBy varchar(8000) = '[year]',
@aggregateColumns varchar(250) = '[Amount]',
@aggregation varchar(250) = 'SUM([Amount])',
@execute int = 0

declare
@sql varchar(8000),
@pivotcols varchar(8000) = '';
declare @result table(result varchar(8000));

set @sql = '
declare
@pivotcols varchar(8000) = '''';
with cte as (
select distinct '+@pivotColumn+', ''[''+cast('+@pivotColumn+' as varchar(250))+'']'' col
from '+@tablename+')
select @pivotcols = @pivotcols + col + '',''
from cte
order by '+@pivotColumn+';
set @pivotcols = left(@pivotcols, len(@pivotcols)-1);
select @pivotcols result';
insert into @result
exec (@sql);
select @pivotcols = result
from @result;

set @sql = '
SELECT *
FROM (
    SELECT 
       '+@groupBy+', '+@pivotColumn+', '+@aggregateColumns+' 
    FROM '+@tablename+'
) AS s
PIVOT
(
    '+@aggregation+'
    FOR '+@pivotColumn+' IN ('+@pivotcols+')
)AS p;';

if @execute = 0
print (@sql);
else exec (@sql);
go

--package into stored procedure and execute
create procedure dbo.dynamicPivot(
@tablenamevarchar(250),
@pivotColumnvarchar(250),
@groupByvarchar(8000),
@aggregateColumnsvarchar(250),
@aggregationvarchar(250),
@executeint = 0)
as
begin;

declare
@sql varchar(8000),
@pivotcols varchar(8000) = '';
declare @result table(result varchar(8000));

set @sql = '
declare
@pivotcols varchar(8000) = '''';
with cte as (
select distinct '+@pivotColumn+', ''[''+cast('+@pivotColumn+' as varchar(250))+'']'' col
from '+@tablename+')
select @pivotcols = @pivotcols + col + '',''
from cte
order by '+@pivotColumn+';
set @pivotcols = left(@pivotcols, len(@pivotcols)-1);
select @pivotcols result';
insert into @result
exec (@sql);
select @pivotcols = result
from @result;

set @sql = '
SELECT *
FROM (
    SELECT 
       '+@groupBy+case @groupBy when '' then '' else ', ' end +@pivotColumn+', '+@aggregateColumns+' 
    FROM '+@tablename+'
) AS s
PIVOT
(
    '+@aggregation+'
    FOR '+@pivotColumn+' IN ('+@pivotcols+')
)AS p;';

if @execute = 0
print (@sql);
else exec (@sql);
end;
go

exec dbo.dynamicPivot
@tablename= '[master].[dbo].[Invoice]',
@pivotColumn= '[month]',
@groupBy= '[Department],[Year]',
@aggregateColumns= '[Amount]',
@aggregation= 'SUM([Amount])',
@execute= 1;
go

--drop created objects
/*
drop table dbo.Invoice;
go
drop procedure dbo.dynamicPivot;
go
*/
set nocount off;

Rate

4.56 (16)

You rated this post out of 5. Change rating

Share

Share

Rate

4.56 (16)

You rated this post out of 5. Change rating