简体   繁体   中英

How do I convert multiple rows into a single row

This is a research database which has (yes I know poorly designed) a database which includes a questionnaire for participants. This questionnaire is asked to the participant at three times in the study (P1/P2/P3)

The table structure for the questionaire;

Questionaire 1.

+--+-------+--------+--+--+--+--+--+---
|PK|Part_ID|Phase_Id|Q1|q2|q3|q4|q5|...
+--+-------+--------+--+--+--+--+--+---
|1 |A010   |P1      |1 |0 |1 |0 |1 |...
+--+-------+--------+--+--+--+--+--+---
|2 |A010   |P2      |0 |1 |0 |1 |0 |...
+--+-------+--------+--+--+--+--+--+---
|3 |A010   |P3      |1 |0 |1 |0 |1 |...
+--+-------+--------+--+--+--+--+--+---

so forth for each participants.

All participants have a maximmum of 3 Phases, may have less. Due to the table structure column count is always the same.

The researcher wants to get all the data onto a single line for input into an analytical program (SPSS). So the output structure need to look like this

+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|Part_ID|P1_Q1|P1_q2|P1_q3|P1_q4|P1_q5|P2_Q1|P2_q2|P2_q3|P2_q4|P2_q5|P3_Q1|P3_q2|P3_q3|P3_q4|P3_q5|
+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|A010   |1    |0    |1    |0    |1    |0    |1    |0    |1    |0    |1    |0    |1    |0    |1    |
+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

Using SQL Server 2008 Express.

I had a look at a few pivot and unpivot examples and dont think they are the right way to go (no aggregation required).

So any pointers would be great.

Regards

Roger (I hope the Demo format comes out ok).

You can UPIVOT your table first and PIVOT it again

SELECT Part_Id, 
       P1_Q1, P1_Q2, P1_Q3, P1_Q4, P1_Q5,
       P2_Q1, P2_Q2, P2_Q3, P2_Q4, P2_Q5,
       P3_Q1, P3_Q2, P3_Q3, P3_Q4, P3_Q5
  FROM
(
  SELECT Part_ID, Phase_Id + '_' + Question Question, Value
    FROM 
  ( 
    SELECT Part_ID, Phase_Id, q1, q2, q3, q4, q5
      FROM Table1
  ) s
  UNPIVOT
  ( 
    Value FOR Question IN (q1, q2, q3, q4, q5) 
  ) u
) s
PIVOT
(
  MAX(Value) FOR Question IN 
  (
    P1_Q1, P1_Q2, P1_Q3, P1_Q4, P1_Q5,
    P2_Q1, P2_Q2, P2_Q3, P2_Q4, P2_Q5,
    P3_Q1, P3_Q2, P3_Q3, P3_Q4, P3_Q5
  )
) p

or by using conditional aggregation

SELECT Part_Id,
       MAX(CASE WHEN Phase_id = 'P1' THEN Q1 END) P1_Q1,
       MAX(CASE WHEN Phase_id = 'P1' THEN Q2 END) P1_Q2,
       MAX(CASE WHEN Phase_id = 'P1' THEN Q3 END) P1_Q3,
       MAX(CASE WHEN Phase_id = 'P1' THEN Q4 END) P1_Q4,
       MAX(CASE WHEN Phase_id = 'P1' THEN Q5 END) P1_Q5,
       MAX(CASE WHEN Phase_id = 'P2' THEN Q1 END) P2_Q1,
       MAX(CASE WHEN Phase_id = 'P2' THEN Q2 END) P2_Q2,
       MAX(CASE WHEN Phase_id = 'P2' THEN Q3 END) P2_Q3,
       MAX(CASE WHEN Phase_id = 'P2' THEN Q4 END) P2_Q4,
       MAX(CASE WHEN Phase_id = 'P2' THEN Q5 END) P2_Q5,
       MAX(CASE WHEN Phase_id = 'P3' THEN Q1 END) P3_Q1,
       MAX(CASE WHEN Phase_id = 'P3' THEN Q2 END) P3_Q2,
       MAX(CASE WHEN Phase_id = 'P3' THEN Q3 END) P3_Q3,
       MAX(CASE WHEN Phase_id = 'P3' THEN Q4 END) P3_Q4,
       MAX(CASE WHEN Phase_id = 'P3' THEN Q5 END) P3_Q5
  FROM Table1
 GROUP BY Part_Id;

Output:

| PART_ID | P1_Q1 | P1_Q2 | P1_Q3 | P1_Q4 | P1_Q5 | P2_Q1 | P2_Q2 | P2_Q3 | P2_Q4 | P2_Q5 | P3_Q1 | P3_Q2 | P3_Q3 | P3_Q4 | P3_Q5 |
|---------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
|    A010 |     1 |     0 |     1 |     0 |     1 |     0 |     1 |     0 |     1 |     0 |     1 |     0 |     1 |     0 |     1 |

Here is SQLFiddle demo

If the number of phases is a maximum of 3 then you can use LEFT JOIN s, for example something like:

SELECT p1.Part_ID, p1.q1, p1.q2, p1.q3, p1.etc,
p2.Part_ID, p2.q1, p2.q2, p2.q3, p2.etc,
p3.Part_ID, p3.q1, p3.q2, p3.q3, p3.etc,
FROM Questionaire p1 
LEFT JOIN Questionaire p2 ON p1.Part_ID = p2.Part_ID AND p1.PhaseId='P1' AND p2.PhaseId='P2'
LEFT JOIN Questionaire p3 ON p2.Part_ID = p3.Part_ID AND p3.PhaseId='P3' 

I haven't tried this so the syntax might not be quite right (eg you may need some brackets).

SELECT Part_ID, SUM(P1_Q1) P1_Q1, SUM(P1_Q2) P1_Q2, SUM(P1_Q3) P1_Q3,
SUM(P1_Q4) P1_Q4, SUM(P1_Q5) P1_Q5, SUM(P2_Q1) P2_Q1, SUM(P2_Q2) P2_Q2,
SUM(P2_Q3) P2_Q3, SUM(P2_Q4) P2_Q4, SUM(P2_Q5) P2_Q5, SUM(P3_Q1) P3_Q1,
SUM(P3_Q2) P3_Q2, SUM(P3_Q3) P3_Q3, SUM(P3_Q4) P3_Q4, SUM(P3_Q5) P3_Q5
FROM 
(  
SELECT Part_ID,P1_Q1,P1_Q2,P1_Q3,P1_Q4,P1_Q5,P2_Q1,P2_Q2,P2_Q3,P2_Q4,P2_Q5,
P3_Q1,P3_Q2,P3_Q3,P3_Q4,P3_Q5,P4_Q1,P4_Q2,P4_Q3,P4_Q4,P4_Q5,P5_Q1,P5_Q2,P5_Q3,
P5_Q4,P5_Q5
FROM 
(SELECT PK, Part_Id, Phase_id, Q1, Q2, Q3, Q4, Q5, Phase_id +'_Q1' AS LocQ1, 
Phase_id + '_Q2' LocQ2, Phase_id + '_Q3' LocQ3, Phase_id + '_Q4' LocQ4,
Phase_id+'_Q5' LocQ5
FROM #t) AS pvt
PIVOT(SUM(Q1) FOR LocQ1 IN (P1_Q1, P2_Q1, P3_Q1, P4_Q1, P5_Q1)) AS pvt1
PIVOT(SUM(q2) FOR LocQ2 IN (P1_Q2, P2_Q2, P3_Q2, P4_Q2, P5_Q2)) AS pvt2
PIVOT(SUM(q3) FOR LocQ3 IN (P1_Q3, P2_Q3, P3_Q3, P4_Q3, P5_Q3)) AS pvt3
PIVOT(SUM(q4) FOR LocQ4 IN (P1_Q4, P2_Q4, P3_Q4, P4_Q4, P5_Q4)) AS pvt4
PIVOT(SUM(q5) FOR LocQ5 IN (P1_Q5, P2_Q5, P3_Q5, P4_Q5, P5_Q5)) AS pvt5
) x GROUP BY Part_ID

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM