如何将行转换为列?

3

我该如何更改这个表格

Name      subject     Mark
Aswin     physics     100
Aswin     chemistry   300
Aswin     maths       200

介绍

Aswin Physics 100 Chemistry 300 Maths 200

Any one please help me.


不是直接的操作,需要将值存入临时表中,然后再从临时表中进行选择。 - Raab
如果您为具有1对多关系的主题使用单独的表,然后使用子查询即可获得所需的结果。 - Sohail Hameed
4个回答

2

SQLFiddle演示

select Name,
       sum(CASE 
          when [subject]='physics' then Mark
       end) as Physics,
       sum(CASE 
          when [subject]='chemistry' then Mark
       end) as chemistry,
       sum(CASE 
          when [subject]='maths' then Mark
       end) as maths


from t group by Name

或者如果您需要单行版本:

SQLFiddle演示

SELECT
   t1.name,
   MemberList = substring((SELECT ( ', ' + subject+' - '+
                                   cast(Mark as varchar(100)) )
                           FROM t t2
                           WHERE t1.name = t2.name
                           ORDER BY 
                              name,
                              subject
                           FOR XML PATH( '' )
                          ), 3, 1000 )FROM t t1
GROUP BY name

2
你可以在SQL Server中使用PIVOT运算符来完成这个任务。
查看这些链接link1link2,它们会展示如何将行转换为列。
希望这可以帮助到你!

1
你需要使用SQL透视表技术,可以查看SQL SERVER – PIVOT and UNPIVOT Table Examples中的示例。使用SQL透视表技术可以将行转换为列,而逆向操作则是将列转换为行。
请注意:我正在检查是否能够提供给您确切的脚本,但目前链接可以帮助您。

更新

代码示例
虽然我还没有用实际数据测试过这个代码,但它可以正常解析。

-- Pivot Table ordered by Name of Student
SELECT Name, Physics, Chemistry, Maths
FROM (
SELECT Name, Subject, Mark
FROM Student) up
PIVOT (SUM(Mark) FOR Student IN (Physics, Chemistry, Maths)) AS pvt
ORDER BY Name

-- Result should be something like
----------------------------------
Name   Physics   Chemistry   Maths
----------------------------------
Aswin  100       300         200

----------------------------------

创建数据透视表需要知道将哪些实际行值转换为列。 如果您觉得有用,我之前写过关于动态数据透视的文章在这里

1

目前还不确定您是想把这些数据分别列在不同的列中还是在同一列中。

如果您想要分别列在不同的列中,那么您可以使用SQL Server 2005中提供的PIVOT函数。

如果您已经知道了要转换的所有值或者数量有限,则可以硬编码查询语句:

select *
from
(
  select name, subject +' '+ cast(mark as varchar(9)) as sub_mark,
    'Subject_'+cast(row_number() over(partition by name 
                                     order by subject) as varchar(10)) col_name
  from subjects
) s
pivot
(
  max(sub_mark)
  for col_name in (Subject_1, Subject_2, Subject_3)
) piv;

请查看带演示的SQL Fiddle。您会注意到,我与其他透视答案略有不同。我将主题/标记放在同一列中,并使用列名Subject_1等。
如果您有未知数量的值,则可以使用动态SQL:
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Subject_'+cast(row_number() over(partition by name 
                                     order by subject) as varchar(10))) 
                    from subjects
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT name,' + @cols + ' from 
             (
                select name, subject +'' ''+ cast(mark as varchar(9)) as sub_mark,
                  ''Subject_''+cast(row_number() over(partition by name 
                                                   order by subject) as varchar(10)) col_name
                from subjects
            ) x
            pivot 
            (
              max(sub_mark)
              for col_name in (' + @cols + ')
            ) p '

execute(@query)

请查看带演示的SQL Fiddle。如果一个name有超过3个科目,则动态SQL版本将增加列数。
两个查询的结果如下:
|  NAME |     SUBJECT_1 | SUBJECT_2 |   SUBJECT_3 |
---------------------------------------------------
| Aswin | chemistry 300 | maths 200 | physics 100 |

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接