SQL Pivot

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
Larry Bristersr. DeveloperAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Kevin CrossConnect With a Mentor Chief Technology OfficerCommented:
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
 
rmm2001Connect With a Mentor Commented:
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
 
Larry Bristersr. DeveloperAuthor Commented:
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
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

 
rmm2001Commented:
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
 
Larry Bristersr. DeveloperAuthor Commented:
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
 
Larry Bristersr. DeveloperAuthor Commented:
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
 
Kevin CrossChief Technology OfficerCommented:
A split is perfectly fine by me. Just glad I could help!

Best regards and happy coding,
Kevin
0
 
Larry Bristersr. DeveloperAuthor Commented:
Excellent folks...thanks
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.