我有两个表,Answers
和Users
,看起来像这样:
Answers (AnswerID, QuestionNumber, Answer, UserID)
Users (UserID, FirstName, LastName)
我可以运行什么 SQL 查询来返回这样的报告:
我有两个表,Answers
和Users
,看起来像这样:
Answers (AnswerID, QuestionNumber, Answer, UserID)
Users (UserID, FirstName, LastName)
我可以运行什么 SQL 查询来返回这样的报告:
您可以使用该PIVOT
函数来转换此数据。您将 (Firstname/Lastname) 作为标题似乎很不寻常,Name
但如果这是您想要的,那么您可以使用以下内容:
select *
from
(
select a.questionnumber,
u.firstname +' '+ u.lastname as Name,
a.answer
from answers a
left join users u
on a.userid = u.userid
) src
pivot
(
max(answer)
for name in ([John Smith], [Bob Jones])
) piv;
结果:
| QUESTIONNUMBER | JOHN SMITH | BOB JONES |
-------------------------------------------
| 1 | blah | test |
| 2 | hsdfk | (null) |
我想你会想要Question Numbers
作为标题,下面有答案:
select *
from
(
select 'QuestionNumber'+cast(a.questionnumber as varchar(10)) questionnumber,
u.firstname +' '+ u.lastname as Name,
a.answer
from answers a
left join users u
on a.userid = u.userid
) src
pivot
(
max(answer)
for questionnumber in ([QuestionNumber1], [QuestionNumber2])
) piv;
结果:
| NAME | QUESTIONNUMBER1 | QUESTIONNUMBER2 |
--------------------------------------------------
| Bob Jones | test | (null) |
| John Smith | blah | hsdfk |
如果您有已知数量的要转换的项目,上述答案将非常有用。但是如果你有一个未知的数字,那么你可以PIVOT
对数据使用动态 SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME('QuestionNumber'+cast(questionnumber as varchar(10)))
from answers
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT Name, ' + @cols + ' from
(
select ''QuestionNumber''+cast(a.questionnumber as varchar(10)) questionnumber,
u.firstname +'' ''+ u.lastname as Name,
a.answer
from answers a
left join users u
on a.userid = u.userid
) x
pivot
(
max(answer)
for questionnumber in (' + @cols + ')
) p '
execute(@query)
结果:
| NAME | QUESTIONNUMBER1 | QUESTIONNUMBER2 |
--------------------------------------------------
| Bob Jones | test | (null) |
| John Smith | blah | hsdfk |
这称为交叉表查询 - 有大量关于如何生成它们的示例;例如:
http://www.simple-talk.com/sql/t-sql-programming/creating-cross-tab-queries-and-pivot-tables-in-sql/
编辑
@Bluefleet 使用 pivot 可能是最好的答案;使用简单的交叉表可能需要您提前了解数据形状的某些方面,因此列本质上是硬编码的 - 如果列是稳定的集合,那么以下应该可以工作:
declare @Answers table (AnswerID int, QuestionNumber int , Answer int , UserID int)
declare @Users table (UserID int , FirstName varchar(10), LastName varchar(10))
declare @Questions table (QuestionNumber int, QuestionName varchar(10))
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (1, 1, 10, 1)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (2, 2, 20, 1)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (3, 3, 30, 2)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (1, 1, 40, 2)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (2, 2, 50, 2)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (3, 3, 60, 3)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (1, 1, 70, 3)
insert into @Answers (AnswerID, QuestionNumber, Answer, UserID) values (2, 2, 80, 3)
insert into @Users (UserID, FirstName, LastName) values (1, 'Tom', 'Smith')
insert into @Users (UserID, FirstName, LastName) values (2, 'Dick', 'Brown')
insert into @Users (UserID, FirstName, LastName) values (3, 'Harry', 'Robinson')
insert into @Questions (QuestionNumber, QuestionName) values (1, 'Question 1')
insert into @Questions (QuestionNumber, QuestionName) values (2, 'Question 2')
insert into @Questions (QuestionNumber, QuestionName) values (3, 'Question 3')
select
QuestionName, MAX(User1) as 'Tom Smith', MAX(User2) as 'Dick Brown', MAX(User3) as 'Harry Robinson'
from
(
select
q.QuestionName,
(case when a.UserID=1 then Answer else null end) as 'User1',
(case when a.UserID=2 then Answer else null end) as 'User2',
(case when a.UserID=3 then Answer else null end) as 'User3'
from @Answers a
join @Users u on u.UserID = a.UserID
join @Questions q on q.QuestionNumber = a.QuestionNumber
) as combined
group by QuestionName
QuestionName Tom Smith Dick Brown Harry Robinson
------------ ----------- ----------- --------------
Question 1 10 40 70
Question 2 20 50 80
Question 3 NULL 30 60