Reputation: 81
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).
Upvotes: 0
Views: 114
Reputation: 31
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
Upvotes: 0
Reputation: 92785
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
Upvotes: 1
Reputation: 3386
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 (e.g. you may need some brackets).
Upvotes: 0