创建具有用作列的相同值的数据透视表

时间:2013-03-18 20:00:34

标签: sql-server-2008 pivot sql-server-express

我有一个表需要使用SQL Management Studio进行转出。这个特殊的例子存在于一个SQLExpress服务器上,但我在2008 r2服务器上有类似的表,我也将它应用于此。

此表包含调查结果(50多个问题和几百个GuestID)。相当直接的转向,但是我已经遇到了多项选择问题和答案输入表格的方式。

我的表格如下:

GuestID      Question                              Answer
1            How old are you?                      30
1            Do you own a car?                     Yes
1            Why do you own a car?                 Convenience
1            Why do you own a car?                 To get the girl
1            Why do you own a car?                 So I can go through the drive-thru

我想转向这个(......保持简短):

GuestID      How old..?     Do you own...?    Why do...?    Why do...?    Why do...?
1            30             Yes               Convenience   To get...     So I can go...

或者,理想情况下,要将答案结合起来转到此处:

GuestID      How old..?     Do you own...?    Why do...?
1            30             Yes               Convenience, To get..., So I can...

我目前正在处理的声明是:

declare @QuestionList as varchar(max)
select @QuestionList = 
    stuff(
    (
        select DISTINCT ',[' + RIGHT(Question,128) + ']'
        from AnnualSurveyAnswers
        where GuestId = 43
        for xml path ('')
        ),1,1,'')

declare @dynamic_PQ as varchar(max)
set @dynamic_PQ = 'select [GuestID], ' + @QuestionList + 
    'from
    (
        Select [GuestID],RIGHT([Question],128)AS Question,[Answer]
        From dbo.AnnualSurveyAnswers
    ) as S

    PIVOT

    (
        MAX([Answer])
        for Question IN (' + @QuestionList + ')
    ) as P
    '
Exec(@dynamic_PQ)

结果:

GuestID     How old...?     Do you own...?     Why do you...?
1           30              Yes                Convenience
2           35              Yes                To get the girl

我必须将DISTINCT添加到@QuestionList,因为我收到有关多次指定列的错误。说得通。我们不能有多个具有相同名称的列。但是,使用DISTINCT,它现在只显示多项选择答案之一。我还添加了MAX来涵盖[Answer]的总需求,但也许我应该使用不同的东西?

有多个选择题,它们可能包含1个响应或8个响应。除了改变原始数据之外还有其他选择吗?

1 个答案:

答案 0 :(得分:4)

可以采取一些措施来获得结果。

如果您希望单独列中的数据,那么我会将row_number()count()包含在一起,将多个答案的问题拆分为与此类似的单独列:

declare @QuestionList as varchar(max)
declare @dynamic_PQ as varchar(max)

select @QuestionList = 
    stuff(
    (
        select DISTINCT ', ' 
          + Quotename(Question
          + case when cnt = 1 then '' else +'_'+cast(rn as varchar(10)) end)
        from
        (
          select distinct guestid,
            RIGHT(Question,128) question,
            count(*) over(partition by question) cnt,
            row_number() over(partition by question, guestid order by question) rn
          from AnnualSurveyAnswers
        ) t1
        -- where GuestId = 1
        for xml path ('')
        ),1,1,'')

set @dynamic_PQ = 'select [GuestID], ' + @QuestionList + 
    'from
    (
        Select [GuestID],
          Question
          + case when cnt = 1 then '''' else +''_''+cast(rn as varchar(10)) end Question,
          [Answer]
        from
        (
          select guestid,
            RIGHT([Question],128) AS Question,
            answer,
            count(*) over(partition by question) cnt,
            row_number() over(partition by question, guestid order by question) rn
          from dbo.AnnualSurveyAnswers
        ) src
    ) as S

    PIVOT

    (
        MAX([Answer])
        for Question IN (' + @QuestionList + ')
    ) as P
    '

Exec(@dynamic_PQ)

请参阅SQL Fiddle with Demo

这给出了结果:

| GUESTID | DO YOU OWN A CAR?_1 | HOW OLD ARE YOU?_1 | WHY DO YOU OWN A CAR?_1 | WHY DO YOU OWN A CAR?_2 |            WHY DO YOU OWN A CAR?_3 |
-----------------------------------------------------------------------------------------------------------------------------------------------
|       1 |                 Yes |                 30 |             Convenience |         To get the girl | So I can go through the drive-thru |
|       2 |                 Yes |                 38 |           Killing frogs |          To get the guy |     So I can go through the tunnel |

如果您希望将答案连接成一列,则可以使用:

declare @QuestionList as varchar(max)
declare @dynamic_PQ as varchar(max)

select @QuestionList = 
    stuff(
    (
        select DISTINCT ', ' 
          + Quotename(Question)
        from
        (
          select guestid,
            RIGHT(Question,128) question
          from AnnualSurveyAnswers
        ) t
        where GuestId = 1
        for xml path ('')
        ),1,1,'')

set @dynamic_PQ = 'select [GuestID], ' + @QuestionList + 
    ' from
    (
        Select [GuestID],
          Question,
          STUFF((SELECT distinct '', '' + a2.answer
                   from AnnualSurveyAnswers a2
                   where src.guestid = a2.guestid
                      and src.question = RIGHT(a2.Question,128)
                      FOR XML PATH(''''), TYPE
                      ).value(''.'', ''NVARCHAR(MAX)'') 
                  ,1,1,'''') answer
        from
        (
          select guestid,
            RIGHT([Question],128) AS Question,
            answer
          from dbo.AnnualSurveyAnswers 
        ) src
    ) as S
    PIVOT

    (
        MAX([Answer])
        for Question IN (' + @QuestionList + ')
    ) as P
    '

Exec(@dynamic_PQ)

SQL Fiddle with Demo。这给出了结果:

| GUESTID | DO YOU OWN A CAR? | HOW OLD ARE YOU? |                                             WHY DO YOU OWN A CAR? |
----------------------------------------------------------------------------------------------------------------------
|       1 |               Yes |               30 |  Convenience, So I can go through the drive-thru, To get the girl |