Solved

How to pivot on multiple columns

Posted on 2012-03-16
9
421 Views
Last Modified: 2012-03-19
I am try to pivot the following data
Normalized data
USI   Review    Status
9        A             A
9        B             A
9        C             B
9        D            A
9        E             D
9        F             B
9        G             H
9        H             E

So that I get the following result
Pivoted Output
USI   Review1   Status1   Review2  Status2   Review3    Status3  
 9           A            A             B             A              C                B

I have written the following code

SELECT USI, [FRS] AS Review1, [Loss Mitigation Decisioning]AS Review2, [Loss Mitigation Handling] AS Review3
FROM
(SELECT USI, Review
    FROM dbo.vwAllReviewStatus
) AS SourceTable
PIVOT
(
max(Review)
FOR [Review] IN ([FRS], [Loss Mitigation Decisioning], [Loss Mitigation Handling])

) AS P1

Which gives me the following result
USI   Review1    Review2     Review3    
9          A                B                  C

I need some help in getting the status1, status2, and status3 fields in

Thanks
0
Comment
Question by:chtullu135
  • 5
  • 2
  • 2
9 Comments
 
LVL 42

Accepted Solution

by:
dqmq earned 400 total points
ID: 37731163
I think that in trying to simplify your question, the SQL you provided got mangled.

That said, try something like this:

declare @tab  table (USI int, Review char(1), status char(1))
insert @tab select 9, 'A', 'A'
insert @tab select 9, 'B', 'A'
insert @tab select 9, 'C', 'B'
insert @tab select 9, 'D', 'A'
insert @tab select 9, 'E', 'D'
insert @tab select 9, 'F', 'B'
insert @tab select 9, 'G', 'H'

Select USI
, max(r1) as Review1, max(s1) as Status1 
, max(r2) as Review2, max(s1) as Status2 
, max(r3) as Review3, max(s1) as Status3 
from
(
Select USI
, case when review='A' then review end as R1 
, case when review='A' then status end as S1 
, case when review='B' then review end as R2 
, case when review='B' then status end as S2 
, case when review='C' then review end as R3 
, case when review='C' then status end as S3 
from @tab
) as x 
group by usi

Open in new window

0
 

Author Comment

by:chtullu135
ID: 37731280
Hello dmg

I tried your code but the status stayed the same for all reviews
For the values of s1, s2, s3  I was expective A, A, B.  I got A ,A, A instead
0
 

Author Comment

by:chtullu135
ID: 37731346
Part of the problem was that

max(r1) as Review1, max(s1) as Status1
, max(r2) as Review2, max(s1) as Status2
, max(r3) as Review3, max(s1) as Status3

Should be
max(r1) as Review1, max(s1) as Status1
, max(r2) as Review2, max(s2) as Status2
, max(r3) as Review3, max(s3) as Status3
0
Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

 
LVL 42

Expert Comment

by:dqmq
ID: 37731395
Good catch--copy/paste error on my part.  Let me know if there are other issues.
0
 

Author Comment

by:chtullu135
ID: 37731936
Hello dqmq,
The code now works but I have some questions as to how it works.  In particular the following segment.  I understand the use of the Case when statement but not of "end as S1".  Could you clarify that for me.

Thanks

Select USI
, case when review='A' then review end as R1
, case when review='A' then status end as S1
, case when review='B' then review end as R2
, case when review='B' then status end as S2
, case when review='C' then review end as R3
, case when review='C' then status end as S3
0
 

Author Comment

by:chtullu135
ID: 37735518
I understand
"case when review='A' then review end as R1 "
but I am trying to figure out how
" case when review='A' then status end as S1 " is returning the correct status.  I don't really want to implement code without understanding how it works.
0
 
LVL 26

Expert Comment

by:Chris Luttrell
ID: 37736258
It will return the correct status if your values in the Review coulumn are distinct for any given USI value, i.e. only one each of A, B, C, D, E, F, G, H for USI=9.
0
 
LVL 26

Assisted Solution

by:Chris Luttrell
Chris Luttrell earned 100 total points
ID: 37736349
To do it with PIVOT like you were trying to do, try this:
SELECT USI,  MAX([Review1]) AS [Review1],  MAX([Status1]) AS [Status1],  MAX([Review2]) AS [Review2],  MAX([Status2]) AS [Status2],   MAX([Review3]) AS [Review3],  MAX([Status3]) AS [Status3],  MAX([Review4]) AS [Review4],  MAX([Status4]) AS [Status4],  MAX([Review5]) AS [Review5],  MAX([Status5]) AS [Status5],  MAX([Review6]) AS [Review6],  MAX([Status6]) AS [Status6],  MAX([Review7]) AS [Review7],  MAX([Status7]) AS [Status7]
FROM (
SELECT USI, Review, Status, 'Review'+CONVERT(VARCHAR(2),rn) ReviewPvtCol, 'Status'+CONVERT(VARCHAR(2),rn) StatusPvtCol
FROM (SELECT USI, Review, Status, ROW_NUMBER() OVER (PARTITION BY USI ORDER BY Review) rn FROM  dbo.vwAllReviewStatus) AS SourceTable
) p
PIVOT
(
max(Review) 
FOR ReviewPvtCol IN ([Review1], [Review2], [Review3], [Review4], [Review5], [Review6], [Review7])
) AS P1
PIVOT
(
max(Status) 
FOR StatusPvtCol IN ([Status1], [Status2], [Status3], [Status4], [Status5], [Status6], [Status7])
) AS P2
GROUP BY USI

Open in new window

You can PIVOT twice but each time consumes the colums used so I created 2 psudo columns ReviewPvtCol and StatusPvtCol and assigned them numbered values to keep Review1 lined up with Status1 and so on.
This way keeps you from having to code in the real values for A-H in the case statements tried above.  I only had your dummy data to go by, but see if it works or is close.  Here is the test code I ran
declare @tab  table (USI int, Review char(1), status char(1))
insert @tab select 9, 'A', 'A'
insert @tab select 9, 'B', 'A'
insert @tab select 9, 'C', 'B'
insert @tab select 9, 'D', 'A'
insert @tab select 9, 'E', 'D'
insert @tab select 9, 'F', 'B'
insert @tab select 9, 'G', 'H'
insert @tab select 19, 'B', 'A'
insert @tab select 19, 'C', 'B'
insert @tab select 19, 'A', 'C'
insert @tab select 19, 'D', 'A'
insert @tab select 19, 'G', 'H'
insert @tab select 19, 'E', 'D'
insert @tab select 19, 'F', 'B'

--Select USI
--, max(r1) as Review1, max(s1) as Status1 
--, max(r2) as Review2, max(s2) as Status2 
--, max(r3) as Review3, max(s3) as Status3 
--from
--(
--Select USI
--, case when review='A' then review end as R1 
--, case when review='A' then status end as S1 
--, case when review='B' then review end as R2 
--, case when review='B' then status end as S2 
--, case when review='C' then review end as R3 
--, case when review='C' then status end as S3 
--from @tab
--) as x 
--group by usi



SELECT USI,  MAX([Review1]) AS [Review1],  MAX([Status1]) AS [Status1],  MAX([Review2]) AS [Review2],  MAX([Status2]) AS [Status2],   MAX([Review3]) AS [Review3],  MAX([Status3]) AS [Status3],  MAX([Review4]) AS [Review4],  MAX([Status4]) AS [Status4],  MAX([Review5]) AS [Review5],  MAX([Status5]) AS [Status5],  MAX([Review6]) AS [Review6],  MAX([Status6]) AS [Status6],  MAX([Review7]) AS [Review7],  MAX([Status7]) AS [Status7]
FROM (
SELECT USI, Review, Status, 'Review'+CONVERT(VARCHAR(2),rn) ReviewPvtCol, 'Status'+CONVERT(VARCHAR(2),rn) StatusPvtCol
FROM (SELECT USI, Review, Status, ROW_NUMBER() OVER (PARTITION BY USI ORDER BY Review) rn FROM @tab) AS SourceTable
) p
PIVOT
(
max(Review) 
FOR ReviewPvtCol IN ([Review1], [Review2], [Review3], [Review4], [Review5], [Review6], [Review7])
) AS P1
PIVOT
(
max(Status) 
FOR StatusPvtCol IN ([Status1], [Status2], [Status3], [Status4], [Status5], [Status6], [Status7])
) AS P2
GROUP BY USI

Open in new window

to get this result
Results from Double Pivot
0
 

Author Closing Comment

by:chtullu135
ID: 37737876
I decided to split points.  Both solutions worked.  But after bench testing both solutions, I found that dqmq's solution executed much faster and so I chose that solution.  However, cgLutteral showed me how to pivot using multiple pivots which I found very informative.
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

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

This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
This article shows gives you an overview on SQL Server 2016 row level security. You will also get to know the usages of row-level-security and how it works
This videos aims to give the viewer a basic demonstration of how a user can query current session information by using the SYS_CONTEXT function
Via a live example, show how to set up a backup for SQL Server using a Maintenance Plan and how to schedule the job into SQL Server Agent.

777 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