黑马程序员--SQL Server 中简单的行转列

来源:互联网 发布:淘宝二维码制作 编辑:程序博客网 时间:2024/06/05 19:23

---------------------- Windows Phones 7手机开发、.Net培训、期待与您交流! ----------------------

前两天在黑马论坛上有人问了一个在SQL中行转列的问题,回答的人挺少的,所以我才写了这篇笔记。

说先来看看我所理解的行转列,假设有如下表结构数据(表名为StudentScore):

Name         Course       Score
 张三            语文            80
 张三            数学            90
 张三            英语            78
 李四            数学            98
 李四            英语            88
 王五            数学           100

如果直接用SELECT * FROM StudentScore 将数据查询出来给用户,恐怕这不是一种比较好的展示方式了,在大多时候需要将数据以下面那样的结构展示给用户:

姓名       数学      英语       语文
李四        98          88        NULL
王五       100       NULL     NULL
张三        90          78          80

那么我们为什么不直接将表创建成下面哪种结构呢,我想这主要是为了应对以后的变更,举个简单的场景,假如我们在最初时将表创建成下面那种结构(三列),那么如果今后要为每个学生新增一门课程的成绩呢,那我们恐怕需要修改表的结构了,这应该是我们尽量避免的一件事了,所以很多时候会将对表列的新增改变成对表行数据的新增,这样在需要新增列的时候只需要添加一条数据就可以了,而在展示的时候再将数据进行 行转列。

好了,我们还是来看看针对问题怎么解决吧,首先我想对Name 进行分组是避免不了的,

SELECT Name,.......  FROM StudentScore GROUP BY Name

中间的省略号怎么写呢,现在数据少,那么我们就写得拙劣一点,我对课程一条一条的列举出来,如果课程列 为语文 就将列 命名为语文,如果课程列为数学就将列命名为数学,最直接的也就是子查询了:

SELECT Name AS 姓名,(SELECT Score FROM StudentScore WHERE Name=SS.Name AND Course='语文') AS 语文 FROM StudentScore AS SS GROUP BY Name

不过我们知道子查询的效率并不是很好,每次对每一个Name 都要全表扫描,所以这里可以改一改

SELECT Name AS 姓名,
SUM(CASE Course WHEN '语文' THEN Score END) AS 语文,
SUM(CASE Course WHEN '数学' THEN Score END) AS 数学,
SUM(CASE Course WHEN '英语' THEN Score END) AS 英语
FROM StudentScore GROUP BY Name,因为这里我们事先知道了有哪三门课程,但是实际应用中我们是不知道表中到底有那些课程的,而且这也不适应增加了一门新课程的情况,所以我们应该把中间 变成动态的才行:

DECLARE @Sql VARCHAR(MAX)
SET @Sql = 'SELECT Name'
SELECT @Sql = @Sql + ',SUM(CASE Course WHEN ''' + Course + ''' THEN Score END) AS ' + Course
FROM StudentScore GROUP BY Course
SET @Sql = @Sql + ' FROM StudentScore GROUP BY Name'
EXEC(@Sql) 

经过执行得到了我们想要的结果,新增课程也不存在问题。好了这问题就到这里了,如果各位黑马高手有更好的解决方案,还请多多指教。

---------------------- Windows Phones 7手机开发、.Net培训、期待与您交流! ----------------------

原创粉丝点击