Solved

SQL Pivot

Posted on 2010-08-13
8
713 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
8 Comments
 
LVL 60

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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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 60

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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Ever needed a SQL 2008 Database replicated/mirrored/log shipped on another server but you can't take the downtime inflicted by initial snapshot or disconnect while T-logs are restored or mirror applied? You can use SQL Server Initialize from Backup…
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
Familiarize people with the process of retrieving data from SQL Server using an Access pass-thru query. Microsoft Access is a very powerful client/server development tool. One of the ways that you can retrieve data from a SQL Server is by using a pa…
Viewers will learn how to use the SELECT statement in SQL and will be exposed to the many uses the SELECT statement has.

734 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