使用分组选择行到列中

时间:2012-03-08 21:37:08

标签: sql-server-2008 tsql

我有几张桌子:

     Exams 
     UserExams 
     UserExamQuestions 
     UserExamAnswers 
     Users 
     ExamQuestions 
     ExamQuestionAnswers

这是我开发的选择

    select ue.DateStarted as 'Date Started', u.LastName as 'Lastname', 
    u.FirstName as 'Firstname', eq.Text as 'Question', eqa.Text as 'Answer',
    eqa.IsCorrect as 'Correct' from Exams e
    join UserExams ue on ue.ExamId = e.Id
    join UserExamQuestions ueq on ueq.UserExamId = ue.Id
    join UserExamAnswers uea on uea.UserExamQuestionId = ueq.Id
    join Users u on u.Id = ue.UserId
    join ExamQuestions eq on eq.Id = ueq.ExamQuestionId
    join ExamQuestionAnswers eqa on eqa.Id = uea.ExamQuestionAnswerId
    where e.Id = 10 and uea.IsSelected = 1
    order by u.LastName, u.FirstName

但不幸的是,它以不受欢迎的方式返回数据。返回的行看起来像这样

    Date Started            Lastname  Firstname      Question             Answer         Correct
    2012-02-26 13:29:50.770 Somename  Somefirstname  Some question text?  Some answer   0
    2012-02-26 13:30:20.000 Othername Otherfirstname Some question text?  Some answer   0
    2012-02-26 15:10:10.212 Fifth     Fifthname      Some question text?  Other answer  1

当然上面的例子是针对三个用户,他们用一些答案回答了一个问题。选定的数据很好,但我需要它是这样的:

   Lastname  Firstname       [Some question text?] Correct
   Somename  Somefirstname   Some answer           0
   Othername Otherfirstname  Some answer           0
   Fifth     Fifthname       Other answer          1

有可能吗?它不一定要快。在代码背后做这件事会很痛苦......我试图转向,但首先 - 我认为我没有正确理解它,其次我不想聚合数据。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

确定。所以我确实看到你的答案,我有一个建议给你。当你说你要用枢轴做到这一点时,你真正纠正的地方。

首先,我为了测试目的简化了数据。测试数据如下:

CREATE TABLE Table1
(
    Lastname VARCHAR(100),  
    Firstname VARCHAR(100),
    Answer VARCHAR(100),
    Question VARCHAR(100),
    Correct BIT
)
INSERT INTO Table1
VALUES
  ('Somename','Somefirstname','Some answer','Some question text?',0),
  ('Somename','Somefirstname','Answer to second question','Second question in same column?',1),
  ('Othername','Otherfirstname','Some answer','Some question text?',0),
  ('Othername','Otherfirstname','Wrong answer to second question','Second question in same column?',0),
  ('Fifth','Fifthname','Other answer','Some question text?',1),
  ('Fifth','Fifthname','Wrong answer to second question','Second question in same column?',0)

您需要获取要转动的唯一列。像这样:

DECLARE @Questions VARCHAR(MAX)
;WITH CTE
AS
(
  SELECT
    ROW_NUMBER() OVER(PARTITION BY Question ORDER BY Question) AS RowNbr,
    ROW_NUMBER() OVER(ORDER BY Question) AS OrderBy,
    Table1.Question
  FROM
    Table1
), CTE2
AS
(
  SELECT
    CTE.OrderBy AS OrderBy,
    1 AS SecondOrder,
    CTE.Question
  FROM
    CTE
  WHERE
    CTE.RowNbr=1
  UNION ALL
  SELECT
    CTE.OrderBy AS OrderBy,
    2 AS SecondOrder,
    'Is '+CTE.Question
  FROM
    CTE
  WHERE
    CTE.RowNbr=1
)
SELECT
  @Questions = COALESCE(@Questions + ','+QUOTENAME(Question),
                     QUOTENAME(Question))
FROM
  CTE2
ORDER BY
  CTE2.OrderBy,
  CTE2.SecondOrder
  • 第一个ROW_NUMBER() OVER(PARTITION BY Question ORDER BY Question)是获取唯一列。稍后我将使用where语句。

  • 第二个ROW_NUMBER() OVER(ORDER BY Question)是订购问题

  • SecondOrder以便您在“是”问题之前订购问题

  • UNION ALLUNION ALL问题和“是”问题

  • @Questions = COALESCE(@Questions + ','+QUOTENAME(Question), ..将列合并为一个varchar

然后我们需要为pivot创建一些动态sql,最后执行它。像这样:

DECLARE @query NVARCHAR(4000)=
N';WITH CTE
AS
(
  SELECT
    Table1.Lastname,
    Table1.Firstname,
    Table1.Answer,
    Table1.Question
  FROM
    Table1
  UNION ALL
  SELECT
    Table1.Lastname,
    Table1.Firstname,
    CAST(Table1.Correct AS VARCHAR(10)) AS Answer,
    ''Is ''+Table1.Question AS Question
  FROM
    Table1
)
SELECT
  *
FROM
(
  SELECT
    CTE.Lastname,
    CTE.Firstname,
    CTE.Answer,
    CTE.Question
  FROM
    CTE
) AS p
PIVOT
(
    MAX(Answer)
    FOR Question IN ('+@Questions+')
) AS pvt'
EXECUTE(@query)
  • 然后我们需要UNION ALL带有“是”问题的问题

  • Correct列已转换为VARCHAR,因为UNION ALL和数据透视不允许使用不同的数据类型

  • 我们将使用MAX聚合来获得我们需要的答案。这是因为枢轴要求我们使用聚合。

  • FOR Question IN ('+@Questions+')是我们在上面的查询中汇总的列。

您可以查看结果和示例数据here

我希望这会对你有所帮助

答案 1 :(得分:2)

Arion - 您的脚本会将所有问题提取到一列中,如下所示:

   Lastname  Firstname       [Some question text?,Second question in same column?] Correct
   Somename  Somefirstname   Some answer                                           0
   Somename  Somefirstname   Answer to second question                             1
   Othername Otherfirstname  Some answer                                           0
   Othername Otherfirstname  Wrong answer to second question                       0
   Fifth     Fifthname       Other answer                                          1
   Fifth     Fifthname       Wrong answer to second question                       0

我需要的是这样的:

   Lastname  Firstname       [Some question text?] [Is Some question answer correct]  [Second question in same column?] [Is Second question in same column answer correct] 
   Somename  Somefirstname   Some answer           0                                  Answer to second question         1          
   Othername Otherfirstname  Some answer           0                                  Wrong answer to second question   0                             
   Fifth     Fifthname       Other answer          1                                  Wrong answer to second question   0