1

SQLManagementStudioを使用してピボットアウトする必要のあるテーブルがあります。この特定の例はSQLExpressサーバー上にありますが、これを適用する2008r2サーバー上にも同様のテーブルがあります。

この表には、調査の結果(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、選択式の回答のうち1つだけが表示されるようになりました。MAXまた、集計要件をカバーするために追加しました[Answer]が、別のものを使用する必要がありますか?

複数の選択肢の質問があり、それらには1つの回答または8つの回答が含まれる場合があります。元のデータを変更する以外のオプションはありますか?

4

1 に答える 1

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 FiddlewithDemoを参照してください。

これにより、次の結果が得られます。

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

回答を1つの列に連結する場合は、次を使用できます。

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 FiddlewithDemoを参照してください。これにより、次の結果が得られます。

| 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 |
于 2013-03-18T20:20:52.347 に答える