如何将数据行转换为列?
Posted
技术标签:
【中文标题】如何将数据行转换为列?【英文标题】:How to convert data rows to columns? 【发布时间】:2010-01-15 08:00:59 【问题描述】:我有一张桌子tblUser
,有列
userId,firstName,LastName,Mobile,.......,QuestionID
我有另一个表,它的名字是tblResults
,有这些列
questionID,Question,choiceID,choice,.........
tblUser
-----------------------------------------------------------------------------
userID - FirstName- LstName -Mobile ... ... ... - QuestionID - ChiceID
-----------------------------------------------------------------------------
001 - xx - yy - 03212 - 01 01
001 - xx - yy - 03212 - 02 02
002 - xxx - yyy - 03425 - 01 02
002 - xxx - yyy - 03425 - 02 01
003 - xxxx - yyyy - 03429 - 03 02
003 - xxxx - yyyy - 03429 - 03 01
------------------------------------------------------------------------------
tblResults
---------------------------------------------------------------------
QuestionID Question ChoiceID Chice .... ....
---------------------------------------------------------------------
01 - **Are you** - 01 - Male
01 - **Areyou** - 02 - Female
02 - **From** - 01 - xxxxx
02 - **FROM** - 02 - yyyyy
---------------------------------------------------------------------
我想得到下表所示的结果
-------------------------------------------------------------------------------
UserID FirstName LastName Mobile **Areyou** **From**
-------------------------------------------------------------------------------
001 - xx - yy - 03212 - Male - yyyyy
002 - xxx - yyy - 03425 - Female - xxxxx
003 - xxxx - yyyy - 03429 - Female - xxxxx
【问题讨论】:
【参考方案1】:您会为每个问题获得具有各自选择的唯一用户,并为每个问题加入一次 tblResults 表:
select
u.userID, u.FirstName, u.LastName, u.Mobile,
q1.Choice as Areyou,
q2.Choice as [From]
from (
select userID, FirstName, LastName, Mobile,
sum(case QuestionId when '01' then ChoiseId else 0 end) as ChoiseId1,
sum(case QuestionId when '02' then ChoiseId else 0 end) as ChoiseId2
from tblUser
) as u
inner join tblResults as q1 on q1.QuestionID = '01' and q1.ChoiseID = u.ChoiseId1
inner join tblResults as q2 on q2.QuestionID = '02' and q2.ChoiseID = u.ChoiseId2
【讨论】:
【参考方案2】:基本上,我们可以为每个问题创建一个表 t (UserID, ChoiceID),然后内连接所有这些表。然后我们得到 (UserID, ChoiceID_for_Question_1, ChoiceID_for_Question_2, ...)。添加用户信息,我们得到了理想的结果。
select t1.UserID, t1.FirstName, t1.LastName, t1.Mobile, t1.Choice, t2.Choice
from
(select u.UserID, u.FirstName, u.LastName, u.Mobile, r.Choice
from tblUser u, tblResults r
where u.questionID = '01' and u.QuestionID=r.QuestionID and u.ChoiceID = r.ChoiceID) t1
inner join
(select u.UserID UserID, r.Choice
from tblUser u, tblResults r
where u.questionID = '02' and u.QuestionID=r.QuestionID and u.ChoiceID = r.ChoiceID) t2
/*
inner join
(...) t3
*/
on t1.UserID = t2.UserID /* and t2.UserID = t3.UserID */
【讨论】:
【参考方案3】:您可以使用PIVOT
来生成您想要的结果。有两种方法,一种是您对列进行硬编码的静态数据透视,另一种是在运行时获取列列表的动态数据透视。
静态枢轴:(参见SQL Fiddle With Demo)
create table tblUser
(
userid int,
fname varchar(10),
lname varchar(10),
mobile int,
questionid int,
choiceid int
)
insert into tblUser values (001, 'xx', 'yy', 03212, 01, 01)
insert into tblUser values (001, 'xx', 'yy', 03212, 02, 02)
insert into tblUser values (002, 'xxx', 'yyy', 03425, 01, 02)
insert into tblUser values (002, 'xxx', 'yyy', 03425, 02, 01)
insert into tblUser values (003, 'xxxx', 'yyyy', 03429, 03, 02)
insert into tblUser values (003, 'xxxx', 'yyyy', 03429, 03, 01)
create table tblResults
(
questionid int,
question varchar(10),
choiceid int,
choice varchar(10)
)
insert into tblresults values (01, 'Are you', 01, 'Male')
insert into tblresults values (01, 'Are you', 02, 'Female')
insert into tblresults values (02, 'From', 01, 'xxxxx')
insert into tblresults values (02, 'From', 02, 'yyyyy')
select *
from
(
select u.userid,
u.fname,
u.lname,
u.mobile,
r.question,
r.choice
from tbluser u
left join tblresults r
on u.questionid = r.questionid
and u.choiceid = r.choiceid
) x
pivot
(
min(choice)
for question in([are you], [from])
) p
动态枢轴:(参见SQL Fiddle with Demo)
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.question)
FROM tblresults c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT userid, fname, lname, mobile, ' + @cols + ' from
(
select u.userid,
u.fname,
u.lname,
u.mobile,
r.question,
r.choice
from tbluser u
left join tblresults r
on u.questionid = r.questionid
and u.choiceid = r.choiceid
) x
pivot
(
min(choice)
for question in (' + @cols + ')
) p '
execute(@query)
两者都会产生相同的结果。
【讨论】:
以上是关于如何将数据行转换为列?的主要内容,如果未能解决你的问题,请参考以下文章