【问题标题】:Convert row to column when data are not numbers当数据不是数字时将行转换为列
【发布时间】:2017-04-01 19:17:46
【问题描述】:

我有一个 Question 表,其中有未知数量的问题。(图中的第一个表)

我还有一个 AnswerSheet 表,记录学生对问题的回答。(图中第二个表)

Create table Question
(
    Id int,
    Text nvarchar(50),

    PRIMARY KEY (Id)
)

Create table AnswerSheet
(
    StudentId int,
    QuestionId int,
    Answer nvarchar(50),

    PRIMARY KEY (StudentId,QuestionId),
    FOREIGN KEY (QuestionId) REFERENCES Question (Id)
)

insert into Question
values(1,'What''s your age'),
      (2,'What''s your gender'),
      (3,'When do you go home'),
      ....


insert into AnswerSheet
values(500,1,'20'),
      (500,2,'Male'),
      (500,3,'5:00pm'),
      (501,1,'50'),
      (502,2,'I don''t know@@'),
      ....

如何编写 SQL 来生成这样的表?

StudentId    What's your age    What's your gender    When do you go home ...
---------    ----------------   -------------------   -------------------
500          20                 Male                  5:00pm              ...
501          50                 NULL                  NULL
502          NULL               I don''t know@@       NULL                ...

我觉得Pivot 很有前途,但我不确定如何使用它,尤其是PIVOT 需要聚合函数,但我的数据不是数字。

【问题讨论】:

标签: sql sql-server tsql pivot


【解决方案1】:

假设你想要动态

示例

Declare @SQL varchar(max) = Stuff((Select ',' + QuoteName(Text) From Question  Order by ID For XML Path('')),1,1,'') 

Select  @SQL = '
Select *
From (
        Select StudentID
              ,Col       = B.Text
              ,Value     = A.Answer
         From AnswerSheet A
         Join Question B on A.QuestionID=B.ID
     ) A
 Pivot (max(Value) For [Col] in (' + @SQL + ') ) p'
Exec(@SQL);

退货

StudentID   What's your age What's your gender  When do you go home
500         20              Male               5:00pm
501         50              NULL               NULL
502         NULL            I don't know@@     NULL

如果有帮助,生成的 SQL 如下所示

Select *
From (
        Select StudentID
              ,Col       = B.Text
              ,Value     = A.Answer
         From AnswerSheet A
         Join Question B on A.QuestionID=B.ID
     ) A
 Pivot (max(Value) For [Col] in ([What's your age],[What's your gender],[When do you go home]) ) p

【讨论】:

  • @LoveRight 我每天都能学到新东西。可以应用任何聚合函数。 --- 很高兴它有帮助。
【解决方案2】:

我知道这个问题已经被接受的人回答了,但我希望这种方法对其他人有所帮助。

您只需使用Pivot无需即可实现您的目标,只需使用Group by 作为下一步:-

Select  b.StudentId,
     Min(Case a.text When 'What''s your age' Then b.answer End) 'What''s your age',
     Min(Case a.text When 'What''s your gender' Then b.answer End) 'What''s your gender',
     Min(Case a.text When 'When do you go home' Then b.answer End) 'When do you go home'
from Question a inner join AnswerSheet b 
on a.id = b.Questionid
Group By StudentId

你提到了未知数量的问题,所以下一个动态代码:-

DECLARE @DynamicQuestions VARCHAR(8000)

SELECT @DynamicQuestions =  Stuff(
(SELECT N' Min(Case a.text When''' + replace (Text,'''','''''')
+ ''' Then b.answer End) '''
+ replace (Text,'''','''''') + ''','
FROM Question FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,1,N'')

select @DynamicQuestions = 
left(@DynamicQuestions,len(@DynamicQuestions)-1) -- for Removing last comma


exec ('Select  b.StudentId, '+ @DynamicQuestions +
'from Question a inner join AnswerSheet b
on a.id = b.Questionid
Group By StudentId' )

结果:-

StudentId   What's your age What's your gender  When do you go home
500             20              Male                5:00pm
501             50              NULL                NULL
502             NULL        I don't know@@          NULL

【讨论】:

  • 您的回答很好,我只想指出,如果您将逗号添加到 stuff() 内的子查询的开头而不是空格,那么您不需要这样做删除尾随逗号的中间部分。
猜你喜欢
  • 2023-03-17
  • 2012-06-14
  • 1970-01-01
  • 2021-03-08
  • 1970-01-01
  • 2022-09-24
  • 2020-03-29
  • 2023-01-25
  • 1970-01-01
相关资源
最近更新 更多