Dynamic Pivot SQL Column Data to Header - sql-server

I would like to transpose the following table so that the first column (tabLabel) becomes the header. I need to do this dynamically, because the number of rows is unknown. I've seen posts on dynamic pivots, but I don't fully understand how this would be done.
tabLabel documentId recipientId Date value
Street Address 1 1 NULL 123 mockingbird lane
City 1 1 NULL city
Patient Phone 1 1 NULL 999-999-9999
Responsible Phone 1 1 NULL 999-999-9999
Gross Income 1 1 NULL 999
Monthly Mortgage/Rent 1 1 NULL 100
Monthly Auto 1 1 NULL 200
Final version:
Street Address City Patient Phone Responsible Phone Gross Income Monthly Mortage/Rent Monthly Auto documentId recipientId Date
123 mockingbird lane city 999-999-9999 999-999-9999 999 100 200 1 1 NULL
Select Query on Original Table:
SELECT [tabLabel]
,[documentId]
,[recipientId]
,[Date]
,[value]
FROM [zDocusign_Document_Tab_Fields]

dynamic sql
-- Build colums
DECLARE #cols NVARCHAR(MAX)
SELECT #cols = STUFF((
SELECT DISTINCT ',' + QUOTENAME([tabLabel])
FROM zDocusign_Document_Tab_Fields
FOR XML PATH('')
), 1, 1, '')
-- Selecting as FOR XML PATH will give you a string value with all of the fields combined
-- separated by comma. Stuff simply removes the first comma.
-- Quotename wraps the [tabLabel] value in brackets to allow for spaces in column name
-- You end up with
-- [City],[Gross Income],[Monthly Auto],[Monthly Mortgage/Rent],[Patient Phone],[Responsible Phone],[Street Address]
-- Build sql
DECLARE #sql NVARCHAR(MAX)
SET #sql = N'
SELECT ' + #cols +'
FROM zDocusign_Document_Tab_Fields
PIVOT (
MAX([value])
FOR [tabLabel] IN (' + #cols + ')
) p
'
-- Execute Sql
EXEC(#sql)

Related

How to map row results from one table as headers for another table in a query [duplicate]

I have read the stuff on MS pivot tables and I am still having problems getting this correct.
I have a temp table that is being created, we will say that column 1 is a Store number, and column 2 is a week number and lastly column 3 is a total of some type. Also the Week numbers are dynamic, the store numbers are static.
Store Week xCount
------- ---- ------
102 1 96
101 1 138
105 1 37
109 1 59
101 2 282
102 2 212
105 2 78
109 2 97
105 3 60
102 3 123
101 3 220
109 3 87
I would like it to come out as a pivot table, like this:
Store 1 2 3 4 5 6....
-----
101 138 282 220
102 96 212 123
105 37
109
Store numbers down the side and weeks across the top.
If you are using SQL Server 2005+, then you can use the PIVOT function to transform the data from rows into columns.
It sounds like you will need to use dynamic sql if the weeks are unknown but it is easier to see the correct code using a hard-coded version initially.
First up, here are some quick table definitions and data for use:
CREATE TABLE yt
(
[Store] int,
[Week] int,
[xCount] int
);
INSERT INTO yt
(
[Store],
[Week], [xCount]
)
VALUES
(102, 1, 96),
(101, 1, 138),
(105, 1, 37),
(109, 1, 59),
(101, 2, 282),
(102, 2, 212),
(105, 2, 78),
(109, 2, 97),
(105, 3, 60),
(102, 3, 123),
(101, 3, 220),
(109, 3, 87);
If your values are known, then you will hard-code the query:
select *
from
(
select store, week, xCount
from yt
) src
pivot
(
sum(xcount)
for week in ([1], [2], [3])
) piv;
See SQL Demo
Then if you need to generate the week number dynamically, your code will be:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(Week)
from yt
group by Week
order by Week
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT store,' + #cols + ' from
(
select store, week, xCount
from yt
) x
pivot
(
sum(xCount)
for week in (' + #cols + ')
) p '
execute(#query);
See SQL Demo.
The dynamic version, generates the list of week numbers that should be converted to columns. Both give the same result:
| STORE | 1 | 2 | 3 |
---------------------------
| 101 | 138 | 282 | 220 |
| 102 | 96 | 212 | 123 |
| 105 | 37 | 78 | 60 |
| 109 | 59 | 97 | 87 |
This is for dynamic # of weeks.
Full example here:SQL Dynamic Pivot
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName= ISNULL(#ColumnName + ',','') + QUOTENAME(Week)
FROM (SELECT DISTINCT Week FROM #StoreSales) AS Weeks
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT Store, ' + #ColumnName + '
FROM #StoreSales
PIVOT(SUM(xCount)
FOR Week IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
I've achieved the same thing before by using subqueries. So if your original table was called StoreCountsByWeek, and you had a separate table that listed the Store IDs, then it would look like this:
SELECT StoreID,
Week1=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=1),
Week2=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=2),
Week3=(SELECT ISNULL(SUM(xCount),0) FROM StoreCountsByWeek WHERE StoreCountsByWeek.StoreID=Store.StoreID AND Week=3)
FROM Store
ORDER BY StoreID
One advantage to this method is that the syntax is more clear and it makes it easier to join to other tables to pull other fields into the results too.
My anecdotal results are that running this query over a couple of thousand rows completed in less than one second, and I actually had 7 subqueries. But as noted in the comments, it is more computationally expensive to do it this way, so be careful about using this method if you expect it to run on large amounts of data .
This is what you can do:
SELECT *
FROM yourTable
PIVOT (MAX(xCount)
FOR Week in ([1],[2],[3],[4],[5],[6],[7])) AS pvt
DEMO
I'm writing an sp that could be useful for this purpose, basically this sp pivot any table and return a new table pivoted or return just the set of data, this is the way to execute it:
Exec dbo.rs_pivot_table #schema=dbo,#table=table_name,#column=column_to_pivot,#agg='sum([column_to_agg]),avg([another_column_to_agg]),',
#sel_cols='column_to_select1,column_to_select2,column_to_select1',#new_table=returned_table_pivoted;
please note that in the parameter #agg the column names must be with '[' and the parameter must end with a comma ','
SP
Create Procedure [dbo].[rs_pivot_table]
#schema sysname=dbo,
#table sysname,
#column sysname,
#agg nvarchar(max),
#sel_cols varchar(max),
#new_table sysname,
#add_to_col_name sysname=null
As
--Exec dbo.rs_pivot_table dbo,##TEMPORAL1,tip_liq,'sum([val_liq]),sum([can_liq]),','cod_emp,cod_con,tip_liq',##TEMPORAL1PVT,'hola';
Begin
Declare #query varchar(max)='';
Declare #aggDet varchar(100);
Declare #opp_agg varchar(5);
Declare #col_agg varchar(100);
Declare #pivot_col sysname;
Declare #query_col_pvt varchar(max)='';
Declare #full_query_pivot varchar(max)='';
Declare #ind_tmpTbl int; --Indicador de tabla temporal 1=tabla temporal global 0=Tabla fisica
Create Table #pvt_column(
pivot_col varchar(100)
);
Declare #column_agg table(
opp_agg varchar(5),
col_agg varchar(100)
);
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(#table) AND type in (N'U'))
Set #ind_tmpTbl=0;
ELSE IF OBJECT_ID('tempdb..'+ltrim(rtrim(#table))) IS NOT NULL
Set #ind_tmpTbl=1;
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(#new_table) AND type in (N'U')) OR
OBJECT_ID('tempdb..'+ltrim(rtrim(#new_table))) IS NOT NULL
Begin
Set #query='DROP TABLE '+#new_table+'';
Exec (#query);
End;
Select #query='Select distinct '+#column+' From '+(case when #ind_tmpTbl=1 then 'tempdb.' else '' end)+#schema+'.'+#table+' where '+#column+' is not null;';
Print #query;
Insert into #pvt_column(pivot_col)
Exec (#query)
While charindex(',',#agg,1)>0
Begin
Select #aggDet=Substring(#agg,1,charindex(',',#agg,1)-1);
Insert Into #column_agg(opp_agg,col_agg)
Values(substring(#aggDet,1,charindex('(',#aggDet,1)-1),ltrim(rtrim(replace(substring(#aggDet,charindex('[',#aggDet,1),charindex(']',#aggDet,1)-4),')',''))));
Set #agg=Substring(#agg,charindex(',',#agg,1)+1,len(#agg))
End
Declare cur_agg cursor read_only forward_only local static for
Select
opp_agg,col_agg
from #column_agg;
Open cur_agg;
Fetch Next From cur_agg
Into #opp_agg,#col_agg;
While ##fetch_status=0
Begin
Declare cur_col cursor read_only forward_only local static for
Select
pivot_col
From #pvt_column;
Open cur_col;
Fetch Next From cur_col
Into #pivot_col;
While ##fetch_status=0
Begin
Select #query_col_pvt='isnull('+#opp_agg+'(case when '+#column+'='+quotename(#pivot_col,char(39))+' then '+#col_agg+
' else null end),0) as ['+lower(Replace(Replace(#opp_agg+'_'+convert(varchar(100),#pivot_col)+'_'+replace(replace(#col_agg,'[',''),']',''),' ',''),'&',''))+
(case when #add_to_col_name is null then space(0) else '_'+isnull(ltrim(rtrim(#add_to_col_name)),'') end)+']'
print #query_col_pvt
Select #full_query_pivot=#full_query_pivot+#query_col_pvt+', '
--print #full_query_pivot
Fetch Next From cur_col
Into #pivot_col;
End
Close cur_col;
Deallocate cur_col;
Fetch Next From cur_agg
Into #opp_agg,#col_agg;
End
Close cur_agg;
Deallocate cur_agg;
Select #full_query_pivot=substring(#full_query_pivot,1,len(#full_query_pivot)-1);
Select #query='Select '+#sel_cols+','+#full_query_pivot+' into '+#new_table+' From '+(case when #ind_tmpTbl=1 then 'tempdb.' else '' end)+
#schema+'.'+#table+' Group by '+#sel_cols+';';
print #query;
Exec (#query);
End;
GO
This is an example of execution:
Exec dbo.rs_pivot_table #schema=dbo,#table=##TEMPORAL1,#column=tip_liq,#agg='sum([val_liq]),avg([can_liq]),',#sel_cols='cod_emp,cod_con,tip_liq',#new_table=##TEMPORAL1PVT;
then Select * From ##TEMPORAL1PVT would return:
Here is a revision of #Tayrn answer above that might help you understand pivoting a little easier:
This may not be the best way to do this, but this is what helped me wrap my head around how to pivot tables.
ID = rows you want to pivot
MY_KEY = the column you are selecting from your original table that contains the column names you want to pivot.
VAL = the value you want returning under each column.
MAX(VAL) => Can be replaced with other aggregiate functions. SUM(VAL), MIN(VAL), ETC...
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(MY_KEY)
from yt
group by MY_KEY
order by MY_KEY ASC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ID,' + #cols + ' from
(
select ID, MY_KEY, VAL
from yt
) x
pivot
(
sum(VAL)
for MY_KEY in (' + #cols + ')
) p '
execute(#query);
select * from (select name, ID from Empoyee) Visits
pivot(sum(ID) for name
in ([Emp1],
[Emp2],
[Emp3]
) ) as pivottable;
Just give you some idea how other databases solve this problem. DolphinDB also has built-in support for pivoting and the sql looks much more intuitive and neat. It is as simple as specifying the key column (Store), pivoting column (Week), and the calculated metric (sum(xCount)).
//prepare a 10-million-row table
n=10000000
t=table(rand(100, n) + 1 as Store, rand(54, n) + 1 as Week, rand(100, n) + 1 as xCount)
//use pivot clause to generate a pivoted table pivot_t
pivot_t = select sum(xCount) from t pivot by Store, Week
DolphinDB is a columnar high performance database. The calculation in the demo costs as low as 546 ms on a dell xps laptop (i7 cpu). To get more details, please refer to online DolphinDB manual https://www.dolphindb.com/help/index.html?pivotby.html
Pivot is one of the SQL operator which is used to turn the unique data from one column into multiple column in the output. This is also mean by transforming the rows into columns (rotating table). Let us consider this table,
If I want to filter this data based on the types of product (Speaker, Glass, Headset) by each customer, then use Pivot operator.
Select CustmerName, Speaker, Glass, Headset
from TblCustomer
Pivot
(
Sum(Price) for Product in ([Speaker],[Glass],[Headset])
) as PivotTable

Trying to pivot multiple columns in T-SQL

I have a query which dynamically generates different number of rows, with varying ID column values. I need to be able to PIVOT this into a columnar result. My current data result is below.
ID Caption FieldName FieldType
--- --------- ------------ ------------
10 Caption 1 Field Name 1 Field Type 1
11 Caption 2 Field Name 2 Field Type 2
12 Caption 3 Field Name 3 Field Type 3
20 Caption 4 Field Name 4 Field Type 4
30 Caption 5 Field Name 5 Field Type 5
My desired result is
10 11 12 20 30
-------- ---------- --------- --------- ---------
Caption 1 Caption 2 Caption 3 Caption 4 Caption 5
Field Name 1 Field Name 2 Field Name 3 Field Name 4 Field Name 5
Field Type 1 Field Type 2 Field Type 3 Field Type 4 Field Type 5
Please note that the values 10, 11, 12, 20 and 30 can change to be something else, so I understand that I need to do some dynamic sql. I want to avoid using CURSORS if possible.
Any suggestions are welcome. Please excuse the formatting
2005 Version
Declare #SQL varchar(max)
Select #SQL = stuff((Select Distinct ',' + QuoteName(ID)+'=max(case when Item='+cast(ID as varchar(25))+' then Value else null end)' From YourTable Order By 1 For XML Path('') ),1,1,'')
Select #SQL = '
Select [Seq],'+#SQL +'
From (
Select Item=A.ID,B.*
From YourTable A
Cross Apply (
Select Seq=1,Value=cast(A.Caption as varchar(max)) Union All
Select Seq=2,Value=cast(A.FieldName as varchar(max)) Union All
Select Seq=3,Value=cast(A.FieldType as varchar(max))
) B
) A
Group By Seq
Order By Seq
'
Exec(#SQL);
Returns
If you don't mind going dynamic
I'm hesitant to remove SEQ (the first column of the results). You can remove [SEQ], from the final query, but I am not sure it would maintain the proper sequence on a larger data set.
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName(ID) From YourTable Order by 1 For XML Path('')),1,1,'')
Select #SQL = '
Select [Seq],' + #SQL + '
From (
Select Item=A.ID,B.*
From YourTable A
Cross Apply (
Select Seq=1,Value=cast(A.Caption as varchar(max)) Union All
Select Seq=2,Value=cast(A.FieldName as varchar(max)) Union All
Select Seq=3,Value=cast(A.FieldType as varchar(max))
) B
) A
Pivot (max(value) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
EDIT - With SEQ Removed from the final Select

Convert a column values to fields and retain other values in sql server

Can someone help me in converting the below mentioned original table to table required? I think I have done it before, it's just I am unable to do it now. Thanks for the help.
Original Table
year school program count
2014 A XYZ 3
2014 A DEF 1
2014 B XYZ 2
2014 B DEF 4
2014 B GHI 5
2014 C XYZ 3
Table Required
YEAR SCHOOL XYZ DEF GHI
2014 A 3 1 0
2014 B 2 4 5
2014 C 3 0 0
Try Dynamic Pivot,
CREATE TABLE #Your_Table
(
YEAR INT,
SCHOOL CHAR(1),
PROGRAM VARCHAR(10),
COUNT INT
)
INSERT INTO #Your_Table
VALUES (2014,'A','XYZ',3),
(2014,'A','DEF',1),
(2014,'B','XYZ',2),
(2014,'B','DEF',4),
(2014,'B','GHI',5),
(2014,'C','XYZ',3)
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
DECLARE #TempColumnname AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName = ISNULL(#ColumnName + ',', '')
+ Quotename(PROGRAM)
FROM (SELECT DISTINCT PROGRAM
FROM #Your_Table) AS Courses
SELECT #TempColumnname = ISNULL(#TempColumnname + ',', '')
+ 'ISNULL(' + Quotename(PROGRAM) + ',0) AS '+Quotename(PROGRAM)
FROM (SELECT DISTINCT PROGRAM
FROM #Your_Table) AS Courses
--PRINT #TempColumnname
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery = N'SELECT Year, School, ' + #TempColumnname
+ 'FROM #Your_Table PIVOT(SUM(Count)
FOR PROGRAM IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC SP_EXECUTESQL
#DynamicPivotQuery
You can try using this query. It first computes a temporary table containing the XYZ, DEF, and GHI count for each record. Then the outer query aggregates these counts for each year/school combination.
SELECT t.year, t.school,
SUM(t.XYZ) AS XYZ, SUM(t.DEF) AS DEF, SUM(t.GHI) AS GHI
FROM
(
SELECT year, school,
CASE WHEN program = 'XYZ' THEN count ELSE 0 END AS XYZ
CASE WHEN program = 'DEF' THEN count ELSE 0 END AS DEF
CASE WHEN program = 'GHI' THEN count ELSE 0 END AS GHI
FROM table
) t
GROUP BY t.year, t.school
Use PIVOT:
SELECT
YEAR,
SCHOOL,
COALESCE([XYZ], 0) [XYZ],
COALESCE([DEF], 0) [DEF],
COALESCE([GHI], 0) [GHI]
INTO
Table_Required
FROM
Original_table
PIVOT
(SUM([count])
FOR program
in([XYZ],[DEF],[GHI])
)AS p
ORDER BY YEAR, SCHOOL

Convert MSAccess Cross tab to MSSQL [duplicate]

I have the following crosstab query in Access:
Transform Count(1) as Count
Select Cust,[Cust#],EntryDate,CloseDate
from Tbl1,Dates
where EntryDate>=[start date]
Group by Cust,[Cust#],EntryDate,CloseDate
Order by EntryDate
Pivot Quote;
I am having difficulty converting this to T-SQL.
Should I be using SSIS for Pivot transformation in order to solve this,
or do we have an equivalent SQL Server query for this?
We don't really have enough information to convert that specific crosstab query, so here is a simple example that may help you achieve your goal:
For a table named [Vehicles] containing...
VehicleID VehicleMake VehicleModel VehicleType
--------- ----------- ------------ ------------
1 Ford Focus Compact car
2 Ford F-150 Pickup truck
3 Dodge RAM 1500 Pickup truck
4 Toyota Tundra Pickup truck
5 Toyota Prius Hybrid car
6 Toyota Tacoma Pickup truck
...the Access crosstab query...
TRANSFORM Count(Vehicles.VehicleID) AS CountOfVehicleID
SELECT Vehicles.VehicleType
FROM Vehicles
GROUP BY Vehicles.VehicleType
PIVOT Vehicles.VehicleMake;
...returns:
VehicleType Dodge Ford Toyota
------------ ----- ---- ------
Compact car 1
Hybrid car 1
Pickup truck 1 1 2
The following T-SQL script accomplishes the same thing
DECLARE
#ColumnList AS NVARCHAR(MAX),
#SQL AS NVARCHAR(MAX)
-- build the list of column names based on the current contents of the table
-- e.g., '[Dodge],[Ford],[Toyota]'
-- required by PIVOT ... IN below
-- ref: http://stackoverflow.com/a/14797796/2144390
SET #ColumnList =
STUFF(
(
SELECT DISTINCT ',' + QUOTENAME([VehicleMake])
FROM [Vehicles]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),
1,
1,
'')
SET #SQL = '
WITH rollup
AS
(
SELECT VehicleMake, VehicleType, COUNT(VehicleID) AS n FROM [Vehicles]
GROUP BY VehicleMake, VehicleType
)
SELECT * FROM rollup
PIVOT (SUM([n]) FOR [VehicleMake] IN (' + #ColumnList + ')) AS Results'
EXECUTE(#SQL)
It returns:
VehicleType Dodge Ford Toyota
------------ ----- ---- ------
Compact car NULL 1 NULL
Hybrid car NULL NULL 1
Pickup truck 1 1 2
drop table #tmpT1
select distinct UserField2 into #tmpT1 from CreateExcelForm
--select * from #tmpT1
DECLARE #PivotColumnHeaders VARCHAR(MAX)
SELECT #PivotColumnHeaders =
COALESCE(
#PivotColumnHeaders + ',[' + cast(UserField2 as varchar) + ']',
'[' + cast(UserField2 as varchar)+ ']'
)
FROM #tmpT1
print(#PivotColumnHeaders)
DECLARE #PivotTableSQL NVARCHAR(MAX)
SET #PivotTableSQL = N'
SELECT *
FROM (
SELECT
* from CreateExcelForm
) AS PivotData
PIVOT (
max(StockCode)
FOR UserField2 IN (
' + #PivotColumnHeaders + '
)
) AS PivotTable
'
EXECUTE(#PivotTableSQL)

Pivot table for string in SQL Server

I have the following table with some details as shown below:
Example:
Creating table product:
create table product
(
slno int,
item nvarchar(20)
);
Inserting some records:
insert into product values(1,'HDD');
insert into product values(2,'PenDrive');
insert into product values(3,'RAM');
insert into product values(4,'DVD');
insert into product values(5,'RAM');
insert into product values(6,'HDD');
Table product contains:
select * from product;
slno item
----------
1 HDD
2 PenDrive
3 RAM
4 DVD
5 RAM
6 HDD
Now I want make a string of items for which i have written the following script:
select distinct
(
select distinct item+','
from product
FOR XML PATH('')
) temp
from product;
Result is:
temp
----------------------
DVD,HDD,PenDrive,RAM,
Note: Now I want to show the result in the following format: (In which I need to use the pivot table with the above query and need to display how many product have sold out).
DVD HDD PenDrive RAM
-----------------------
1 2 1 2
My Try:
select DVD,HDD,PenDrive,RAM
from
(
select distinct
(
select distinct item+','
from product
FOR XML PATH('')
) temp
from product
) as a
pivot
(
count(temp)
for temp in(DVD,HDD,PenDrive,RAM)
) pt
But getting result :
DVD HDD PenDrive RAM
------------------------
0 0 0 0
You don't need to use the FOR XML PATH to create a string of the columns unless you need a dynamic SQL version to get your final result.
Using PIVOT you can easily hard-code your values for your query:
select DVD, HDD, PenDrive, RAM
from
(
select item
from product
) d
pivot
(
count(item)
for item in (DVD, HDD, PenDrive, RAM)
) piv;
See SQL Fiddle with Demo.
Now if you had an unknown values that you needed to be the final columns, then you'd create a list of the items and execute a SQL string via dynamic SQL similar to:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(item)
from product
group by item
order by item
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
select item
from product
) x
pivot
(
count(item)
for item in (' + #cols + ')
) p '
exec sp_executesql #query;
See SQL Fiddle with Demo

Resources