Solved

SQL Pivot

Posted on 2010-08-13
8
706 Views
Last Modified: 2012-08-13
I have data in a table that I need to do a PIVOT on

Currently

TYPE      Jan     Feb   Mar   ....
Apd         1          2       0
Rsd          2         1        3

I need

Month        Apd       Rsd
Jan              1           2
Feb             2            1
Mar             0            3
0
Comment
Question by:lrbrister
  • 4
  • 2
  • 2
8 Comments
 
LVL 59

Accepted Solution

by:
Kevin Cross earned 350 total points
ID: 33434133
lrbrister,

It looks like first you need to unpivot on the month and then pivot on the type. Sorting will be a different story as you have text months, so you will have to equate Jan to 1 ... and as you can see you will have to completely fill in (hard-code) the other months and other types in the pivot statements. If you need this to be dynamic for [type] then you need to use dynamic SQL. For the sort, I recommend you have a table of months short name with associated month number then you can use that to sort efficiently.
select *
from (

select [type], [value], [month]
from your_table_name
unpivot(value for [month] in (Jan, Feb, Mar)) u

) d
pivot(sum(value) for [type] in (Apd, Rsd))p
;

Open in new window

0
 
LVL 7

Assisted Solution

by:rmm2001
rmm2001 earned 150 total points
ID: 33437698
going on what mwvisa1 said...here's how you could make it dynamic. the first query pulls the values in the type table and makes them in a delimited list, The second one goes and makes your column headings into a delimited list. the 3rd one is a dynamic version of what mwvist1 posted.


----get the different types
DECLARE @typequery NVARCHAR(4000)
DECLARE @typenames NVARCHAR(4000)
SET @typequery = '
   ;WITH CTE ( CategoryId, typenames, type, length ) 
          AS ( SELECT DISTINCT 1 CategoryId, CAST( '''' AS VARCHAR(8000) ), CAST( '''' AS VARCHAR(8000)) type, 0
                 FROM table0
                GROUP BY type
                UNION ALL
               SELECT 1 CategoryId, CAST( p.[type] + 
                      CASE WHEN length = 0 THEN '''' ELSE '', '' END + typenames AS VARCHAR(8000) ), 
                      CAST( p.[type]  AS VARCHAR(8000)), length + 1
                 FROM CTE c
                JOIN table0 p
                   ON p.type > c.type) 
    SELECT @typenames = typenames 
      FROM ( 
      SELECT CategoryId, typenames, 
                    RANK() OVER ( PARTITION BY CategoryId ORDER BY length DESC )
               FROM CTE  ) D ( CategoryId, typenames, rank )
     WHERE rank = 1 '
   
EXEC sp_executesql
@typequery,
N'@typenames NVARCHAR(4000) OUTPUT', 
@typenames OUTPUT

----now get the columns 
DECLARE @colsquery NVARCHAR(4000)
DECLARE @cols NVARCHAR(4000)
SET @colsquery = '
			SELECT @cols = LEFT(cols, LEN(cols) - 1)
			FROM information_schema.columns p1
		    CROSS APPLY ( SELECT column_name + '',''
							 FROM information_schema.columns p2
							 WHERE p2.table_name = p1.table_name AND column_name <> ''Type''
							 ORDER BY table_name
							 FOR XML PATH('''') )  D ( cols )
			WHERE table_name = ''table0''
'
EXEC sp_executesql
@colsquery,
N'@cols NVARCHAR(4000) OUTPUT',
@cols OUTPUT
SELECT @cols

----execute the pivot query
DECLARE @pivotquery NVARCHAR(4000)
SET @pivotquery = '
SELECT *
FROM (

	SELECT [type], [value], [month]
	FROM table0
	UNPIVOT(value FOR [month] IN (' + @cols + ' )) u

) d
PIVOT(SUM(value) FOR [type] IN (' + @typenames + '))p
;'
EXEC sp_executesql
@pivotquery

Open in new window

0
 

Author Comment

by:lrbrister
ID: 33444725
rmm2001:
I'm not "getting it" for some reason.
Take a look at my screenprint...that's what I need to "unpivot so that the rows are the columns and vice versa...

screenprint.jpg
0
Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

 
LVL 7

Expert Comment

by:rmm2001
ID: 33444758
try what mwvista1 said. that should get you what you want i think. the thing i posted was to make it dynamic so don't have to type in every single field for the pivot/unpivot commands. you'd just type in the table name.


select *
from (

select [type], [value], [month]
from your_table_name
unpivot(value for [month] in (Jan, Feb, Mar)) u

) d
pivot(sum(value) for [type] in (Apd, Rsd))p
;

Open in new window

0
 

Author Comment

by:lrbrister
ID: 33444978
Ok folks...getting there...
Theonly issue I have is that it's not sorting the months
 
The select below returns...
ahoffman Apr 0 0
ahoffman Aug 0 1
ahoffman Dec 0 0
ahoffman Feb 0 0
ahoffman Jan 0 0
ahoffman Jul 11 5
ahoffman Jun 3 3

select *  
from (  
  
select [rep],[EventType], [value], [month]  
from dbo.tblRepScoreCard
unpivot(value for [month] in (Jan, Feb, Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec)) u  
  
) d  
pivot(sum(value) for [EventType] in (PASigned, PAComplete))p  
order by p.rep, p.month
;

Open in new window

0
 

Author Comment

by:lrbrister
ID: 33445131
hey folks...
I got it.  Used most of mwvisa1: and a touch of rmm2001 in the final solution (Attached)
mwvisa1...you mind a 350-150 split with  rmm2001?

select *
from (  
  
select [rep],[EventType], [value], [month]  
from dbo.tblRepScoreCard
unpivot(value for [month] in (Jan, Feb, Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec)) u  
  
) d  
pivot(sum(value) for [EventType] in (PASigned, PAComplete, Dropped, Funded))p  
order by p.rep, CHARINDEX(Left(p.[month],3),'xxJANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC')/3
;

Open in new window

0
 
LVL 59

Expert Comment

by:Kevin Cross
ID: 33445164
A split is perfectly fine by me. Just glad I could help!

Best regards and happy coding,
Kevin
0
 

Author Closing Comment

by:lrbrister
ID: 33445243
Excellent folks...thanks
0

Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Everyone has problem when going to load data into Data warehouse (EDW). They all need to confirm that data quality is good but they don't no how to proceed. Microsoft has provided new task within SSIS 2008 called "Data Profiler Task". It solve th…
Use this article to create a batch file to backup a Microsoft SQL Server database to a Windows folder.  The folder can be on the local hard drive or on a network share.  This batch file will query the SQL server to get the current date & time and wi…
Via a live example, show how to extract information from SQL Server on Database, Connection and Server properties
Via a live example, show how to extract insert data into a SQL Server database table using the Import/Export option and Bulk Insert.

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question