1

我有一个包含以下数据的 SQL Server 视图:

ID   clientID  surveyID    questionID     q_optionID   q_ans_text
-----------------------------------------------------------------
1       1          1           1            NULL            Yes
2       1          1           2             18             NULL 
3       1          1           3             19             NULL
4       2          1           1            NULL             No
5       2          1           2             18             NULL
6       2          1           3             19             NULL
7       3          2           1            NULL            Yes 
8       3          2           2             15             NULL 
9       3          2           3             13             NULL   

我希望结果是这样的:

ClientID  SurveyID   Q1    Q2    Q3  
------------------------------------
   1          1     Yes    18    19   
   2          1      No    18    19   
   3          2     Yes    15    13 

忽略条件NULL值并将正确答案放在列中的位置。我看过数据透视表示例,但它们似乎专注于单列数据透视表。

4

3 回答 3

3

为了执行此转换,您将需要UNPIVOT然后PIVOT数据。UNPIVOT将从您的 和 列中获取值并将q_optionIDq_ans_text转换为两列,其中一列具有值和列名。

有两种方法可以做到PIVOT这一点,可以使用静态版本对所有值进行硬编码,也可以使用动态 sql。为了UNPIVOT获得数据,您需要确保数据具有相同的数据类型,因此可能需要进行转换。

静态枢轴:

select clientid, surveyid, 
    questionid,
    value,
    col
  from
  (
    select clientid, surveyid, questionid,
      cast(q_optionID as varchar(4)) q_optionID,
      q_ans_text
    from yourtable
  ) s
  unpivot
  (
    value
    for col in (q_optionID, q_ans_text)
  ) un

请参阅带有演示的 SQL Fiddle

反透视结果:

| CLIENTID | SURVEYID | QUESTIONID | VALUE |        COL |
---------------------------------------------------------
|        1 |        1 |          1 |   Yes | q_ans_text |
|        1 |        1 |          2 |    18 | q_optionID |
|        1 |        1 |          3 |    19 | q_optionID |
|        2 |        1 |          1 |    No | q_ans_text |
|        2 |        1 |          2 |    18 | q_optionID |
|        2 |        1 |          3 |    19 | q_optionID |
|        3 |        2 |          1 |   Yes | q_ans_text |
|        3 |        2 |          2 |    15 | q_optionID |
|        3 |        2 |          3 |    13 | q_optionID |

然后,您将应用于PIVOT结果以获得最终产品。

select *
from
(
  select clientid, surveyid, 
    'Q'+cast(questionid as varchar(10)) question,
    value
  from
  (
    select clientid, surveyid, questionid,
      cast(q_optionID as varchar(4)) q_optionID,
      q_ans_text
    from yourtable
  ) s
  unpivot
  (
    value
    for col in (q_optionID, q_ans_text)
  ) un
) src
pivot
(
  max(value)
  for question in (Q1, Q2, Q3)
) piv

请参阅带有演示的 SQL Fiddle

动态枢轴:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Q'+cast(questionid as varchar(10))) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT clientid, surveyid,' + @cols + ' from 
             (
                select clientid, surveyid, 
                  ''Q''+cast(questionid as varchar(10)) question,
                  value
                from
                (
                  select clientid, surveyid, questionid,
                    cast(q_optionID as varchar(4)) q_optionID,
                    q_ans_text
                  from yourtable
                ) s
                unpivot
                (
                  value
                  for col in (q_optionID, q_ans_text)
                ) un
            ) x
            pivot 
            (
                max(value)
                for question in (' + @cols + ')
            ) p '

execute(@query)

请参阅带有演示的 SQL Fiddle

UNION ALL/聚合与案例版本:

现在,如果您在没有的系统中工作,PIVOT则可以使用UNION ALLto和带有toUNPIVOT的聚合函数:CASEPIVOT

select clientid, surveyid,
  max(case when questionid = 1 then value end) Q1,
  max(case when questionid = 2 then value end) Q2,
  max(case when questionid = 3 then value end) Q3
from
(
  select clientid, surveyid, questionid, cast(q_optionID as varchar(10)) value, 'q_optionID' col
  from yourtable
  union all
  select clientid, surveyid, questionid, q_ans_text value, 'q_ans_text' col
  from yourtable
) unpiv
group by clientid, surveyid

请参阅带有演示的 SQL Fiddle

这三个都将产生相同的结果:

| CLIENTID | SURVEYID |  Q1 | Q2 | Q3 |
---------------------------------------
|        1 |        1 | Yes | 18 | 19 |
|        2 |        1 |  No | 18 | 19 |
|        3 |        2 | Yes | 15 | 13 |
于 2012-12-11T22:40:27.063 回答
1

没有明确的 unpivot 的示例。不过,这仍然是一个非常有用的技术!

Select
  clientID, 
  SurveyID, 
  [1] as Q1, 
  [2] as Q2,
  [3] as Q3
From (
  Select
    clientID,
    surveyID,
    questionID,
    IsNull(Cast(q_optionID as varchar(10)), q_ans_text) answer
  From
    Answers
) a
Pivot (
  Max(answer)
  For questionID In ([1], [2], [3])
) p

http://sqlfiddle.com/#!6/8552a/8

于 2012-12-11T22:59:21.830 回答
0
select
  clientid, surveyid,
  max(case when questionid = 1 then coalesce(q_ans_text, cast(q_optionID as char)) else null end) as Q1,
  max(case when questionid = 2 then coalesce(q_ans_text, cast(q_optionID as char)) else null end) as Q2,
  max(case when questionid = 3 then coalesce(q_ans_text, cast(q_optionID as char)) else null end) as Q3
 from yourtable
 group by clientid, surveyid

http://sqlfiddle.com/#!18/9163ba/11

于 2020-09-26T16:53:11.743 回答