如何将数据行转换为列?

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)

两者都会产生相同的结果。

【讨论】:

以上是关于如何将数据行转换为列?的主要内容,如果未能解决你的问题,请参考以下文章

MS Access SQL 将行转换为列

将 Pandas DataFrame 的行转换为列标题,

如何将多个重复行转换为列,然后在记事本++中从列转换回行

如何在sql中将行转换为列

这是一个员工数据,我想使用数据透视将行数据转换为列

如何使用数据透视在 Oracle 中将行转换为列