Click here to Skip to main content
15,896,063 members
Articles / Database Development / SQL Server

Pivot two or more columns in SQL Server 2005

Rate me:
Please Sign up or sign in to vote.
4.77/5 (22 votes)
18 Dec 2008CPOL4 min read 179.6K   2K   58  
A workaround for the limitation of only being able to pivot one column.


DECLARE 
	@List VARCHAR(1000),
	@SQL VARCHAR(8000)

--Make sure the variables are not null
SET @List = ''
SET @SQL = ''

--I always include this during development in case the script fails and leaves the table in the tempdb
IF  EXISTS (SELECT * FROM tempdb.sys.objects WHERE name like '#TblX%' AND type in (N'U'))
	DROP TABLE [dbo].#TblX

--Create a temp table because we cannot pass a table var into dynamic SQL
CREATE TABLE #TblX(Department VARCHAR(100),Staff INT, Yr VARCHAR(10))

--Insert the male records Note the case statement for the gender and the label creation
INSERT [#TblX]	
SELECT 
	D.Department,
	SUM(CASE E.Gender WHEN 'M' THEN 1 ELSE 0 END) Staff, -- we only need the male staff in this column
	CONVERT(CHAR(4),DATEPART(yy,E.HireDate)) + '-M' Yr -- set the may year label
FROM HumanResources.Employee E
	INNER JOIN HumanResources.vEmployeeDepartment D ON D.EmployeeID = E.EmployeeID

GROUP BY 
	D.Department,
	DATEPART(yy,E.HireDate)

UNION	
-- Now get the female staff, changing the label
SELECT 
	D.Department,
	SUM(CASE E.Gender WHEN 'F' THEN 1 ELSE 0 END) Staff,
	CONVERT(CHAR(4),DATEPART(yy,E.HireDate)) + '-F' Yr -- set the female year label
FROM HumanResources.Employee E
	INNER JOIN HumanResources.vEmployeeDepartment D ON D.EmployeeID = E.EmployeeID
GROUP BY 
	D.Department,
	DATEPART(yy,E.HireDate)

--We now need to build a CSV list of labels to use
DECLARE @TblY TABLE(Yr CHAR(6))
INSERT @TblY 
SELECT  DISTINCT Yr FROM [#TblX]
	
--Get the dynamic list of years (DISTINCT and the concatenation does not work)
SELECT @List = ISNULL(@List,'') + CASE WHEN ISNULL(@List,'') = '' THEN '[' + yr + ']' ELSE ',[' + Yr + ']' end
FROM @TblY
ORDER BY Yr

--Now to build the pivot query
Set @SQL = 'Select Department, ' + @List + char(13) 
--Inside query
Set @SQL = @SQL + 'From (Select Department, Yr, Staff ' + char(13) 
Set @SQL = @SQL + 'FROM #TblX F) P ' + char(13) 
--Pivot 
Set @SQL = @SQL + 'Pivot (Max(Staff) For Yr In ('  + @List + ')) as Pvt' + char(13) 


Print @SQL
Exec (@SQL)

DROP TABLE [#TblX]


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired None
Australia Australia
Started my programming life writing Excel 1.0 macros, God what a long time ago.

Now I'm a dotnet developer, I get to influence direction, play with new toys, build stuff, life is wonderful.

Greatest buzz you can get, walk past a row of desks and see your application running on all of them (and getting paid).

Greatest irritant, pouring 12 months of knowledge and experience into an empty head only to have it leave.

And now I'm retired, no deadlines, no meetings, no managers (except the ONE) and no users!

Comments and Discussions