Web Technologies

BLOG for Web Technologies

Freewares, Free E-Books Download, SEO, Tips, Tricks, Tweaks, Latest News, .Net, PHP, ASP, ASP.Net, CSP, MS SQL Server, MySQL, Database
earnptr.com
Wednesday, September 12, 2007
Dynamic Crosstab (Using Pivot in SQL Server)- How it works
This example assumes the following statement taken from the first example using the pubs
database. The statement to execute crosstab is:

EXECUTE crosstab 'select title from titles inner join sales on (sales.title_id=titles.title_id) group by title',
'sum(qty)', 'stor_id', 'stores'

@pivot is the name of the pivot column from the table named in @table. From the statement above
it is stor_id. The following statement creates an empty table named ##pivot with one column named
pivot.

EXEC ('SELECT ' + @pivot + ' AS pivot INTO ##pivot FROM ' + @table + ' WHERE 1=2')

The next statement populates ##pivot with the unique values from the @pivot column (stor_id)
in the table named in @table (stores).

EXEC ('INSERT INTO ##pivot SELECT DISTINCT ' + @pivot + ' FROM ' + @table + ' WHERE '
+ @pivot + ' Is Not Null')

The result of the statement above puts the following values in the table ##pivot:

6380
7066
7067
7131
7896
8042

The following statement initializes the variable @sql to a single blank space. The parameter @sumfunc
was passed to crosstab as 'sum(qty)'. This statement has expanded it to 'sum(qty END)'.

SELECT @sql='', @sumfunc=stuff(@sumfunc, len(@sumfunc), 1, ' END)' )

The following statement selects the delimiter (@delim) to be used when to bound the column headings
from ##pivot. If the datatype is char or date a single quote (') is used. Otherwise a space is used. Since
stor_id, our pivot column is char(4) in the table stores, the delimiter is a single quote (').

SELECT @delim=CASE Sign( CharIndex('char', data_type)+CharIndex('date', data_type) )
WHEN 0 THEN '' ELSE '''' END FROM tempdb.information_schema.columns
WHERE table_name='##pivot' AND column_name='pivot'

The following statement creates the columns based on the values in ##pivot. The parameter @sumfunc
started out as 'sum(qty)' as passed to crosstab. It was expanded to 'sum(qty END)' two statements ago.
Now it will be expanded again and added to @sql for each value in ##pivot.

SELECT @sql=@sql + '''' + convert(varchar(100), pivot) + ''' = ' +
stuff(@sumfunc,charindex( '(', @sumfunc )+1, 0, ' CASE ' + @pivot + ' WHEN '
+ @delim + convert(varchar(100), pivot) + @delim + ' THEN ' ) + ', ' FROM ##pivot

The phrase ['''' + convert(varchar(100), pivot) + ''' = ' ] takes the value from ##pivot and puts it in single
quotes and adds and equal sign. For the first entry in ##pivot that is ['6380' = ].

@sumfunc has the string 'sum(qty END)'. The phrase [stuff(@sumfunc,charindex( '(', @sumfunc )+1, 0,
' CASE ' + @pivot + ' WHEN ' + @delim + convert(varchar(100), pivot) + @delim + ' THEN ' ) ] expands
that to 'sum( CASE stor_id WHEN '6380' THEN qty END)'. A comma (,) is then added to the string.

For the first value from ##pivot we have the following phrase in @sql:
['6380' = sum( CASE stor_id WHEN '6380' THEN qty END), ].

A similar phrase is added for each value in ##pivot.

We are now finished with the temporary table ##pivot and it is dropped.

DROP TABLE ##pivot

The final comma(,) on @sql is dropped.

SELECT @sql=left(@sql, len(@sql)-1)

The value in the parameter @select was passed to crosstab. It is:

select title from titles inner join sales on (sales.title_id=titles.title_id) group by title

The following statement locates [ FROM ] in @select and inserts [, ], the contents of @sql, then another
blank before the word from. This completes the SQL string to be executed.

SELECT @select=stuff(@select, charindex(' FROM ', @select)+1, 0, ', ' + @sql + ' ')

The resulting string @select is:

select title , '6380' = sum( CASE stor_id WHEN '6380' THEN qty END), '7066' = sum( CASE stor_id WHEN '7066' THEN qty END), '7067' = sum( CASE stor_id WHEN '7067' THEN qty END), '7131' = sum( CASE stor_id WHEN '7131' THEN qty END), '7896' = sum( CASE stor_id WHEN '7896' THEN qty END), '8042' = sum( CASE stor_id WHEN '8042' THEN qty END) from titles inner join sales on (sales.title_id=titles.title_id) group by title

The statement EXEC (@select) completes the crosstab. Try it.

Labels: , ,

posted by WebTeks @ 2:04 AM   0 comments
Previous Post
Archives
Links
Template by

Free Blogger Templates

BLOGGER

Subscribe in NewsGator Online Subscribe in Rojo Add to Google Add to netvibes Subscribe in Bloglines Web Developement Blogs - BlogCatalog Blog Directory Blogarama - The Blog Directory Blog Directory & Search engine Computers Blogs - Blog Top Sites Top Computers blogs