如何将多行转换为单行

时间:2014-01-20 05:23:43

标签: sql sql-server-2008 tsql

这是一个研究数据库,有(我知道设计很差)一个数据库,其中包括参与者的调查问卷。该调查问卷在研究中三次向参与者询问(P1 / P2 / P3)

问卷的表格结构;

问卷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 |...
+--+-------+--------+--+--+--+--+--+---
每个参与者都是如此。

所有参与者的最大阶段为3阶段,可能较少。由于表结构列数始终相同。

研究人员希望将所有数据放到一行中以输入分析程序(SPSS)。所以输出结构需要看起来像这样

+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|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    |
+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

使用SQL Server 2008 Express。

我看了几个透视和未透明的例子,并且不认为它们是正确的方法(不需要聚合)。

所以任何指针都会很棒。

此致

罗杰 (我希望Demo格式出来没问题。)

3 个答案:

答案 0 :(得分:1)

您可以先UPIVOT您的牌桌,然后再PIVOT

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

或使用条件聚合

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;

输出:

| 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 |

这是 SQLFiddle 演示

答案 1 :(得分:0)

如果阶段的数量最多为3,那么您可以使用LEFT JOIN s,例如:

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' 

我没有尝试过,所以语法可能不太正确(例如,您可能需要一些括号)。

答案 2 :(得分:0)

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