• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 436
  • Last Modified:

How to pivot on multiple columns

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
chtullu135
Asked:
chtullu135
  • 5
  • 2
  • 2
2 Solutions
 
dqmqCommented:
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
 
chtullu135Author Commented:
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
 
chtullu135Author Commented:
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
Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

 
dqmqCommented:
Good catch--copy/paste error on my part.  Let me know if there are other issues.
0
 
chtullu135Author Commented:
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
 
chtullu135Author Commented:
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
 
Chris LuttrellSenior Database ArchitectCommented:
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
 
Chris LuttrellSenior Database ArchitectCommented:
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
 
chtullu135Author Commented:
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

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 5
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now