我有几张 table :
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
这可能吗?它不必很快。在代码后面执行此操作会很痛苦...我正在尝试枢轴,但首先 - 我认为我没有正确理解它,其次我不想聚合数据。
感谢您的帮助。
最佳答案
好的。所以我确实看到你的回答,我给你一个建议。当您说要使用枢轴来完成此操作时,您实际上是正确的。
所以首先我出于测试目的简化了您的数据。测试数据如下:
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
是为了让您将该问题排序在“Is”问题之前UNION ALL
是为了让我们能够UNION ALL
问题和"is"问题@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)
然后我们需要将问题与“Is”问题
UNION ALL
正确
列被转换为VARCHAR
,因为UNION ALL
和数据透视不允许不同的数据类型我们将使用
MAX
聚合来获取我们需要的答案。这是因为数据透视表要求我们使用聚合。FOR Question IN ('+@Questions+')
是我们在上面的查询中连接的列。
可以看到结果和示例数据here
希望这对你有帮助
关于sql-server-2008 - 通过分组将行选择到列中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9625339/