sql行列转换 的处理

行列转换在实际使用中,比如报表中使用比较多,处理方式也很多,有程序处理,存储过程处理,中建表或者sql处理本文探讨一下sql处理,士例来自 北大青鸟合肥圣大中心提供的内部测试题说句心里话,这题给他们做,确实难了。

原表:   姓名     科目   成绩             张三     语文    80             张三     数学    90             张三     物理    85             李四     语文    85             李四     物理    82             李四     英语    90             李四     政治    70             王五     英语    90    转换后的表:  姓名       数学    物理     英语    语文    政治    (0是缺考) 李四         0         82        90      85       70               王五         0          0         90       0         0               张三        90        85         0       80        0  建表并插入测试数据    create table cj  --创建表cj                             (                                                                ID       Int IDENTITY (1,1)     not null, -             Name     Varchar(50),                                   Subject  Varchar(50),                                   Result   Int,                                           primary key (ID)      --定义ID为表cj的主键          );                                                                                                              Insert into cj                                          Select '张三','语文',80 union all                       Select '张三','数学',90 union all                       Select '张三','物理',85 union all                         Select '李四','语文',85 union all                    Select '李四','物理',82 union all                    Select '李四','英语',90 union all                    Select '李四','政治',70 union all                    Select '王五','英语',90                对于单表,处理的sql相对简单       Declare @sql varchar(8000)  Set @sql = 'Select Name as 姓名'--1  Select @sql = @sql + ',sum(case Subject when '''+Subject+''' then Result else 0 end) ['+Subject+']'  from (select distinct Subject from cj) as cj  --2 把所有唯一的科目的名称都列举出来  Select @sql = @sql+' from cj group by name'--3  Exec (@sql)  这是一个复合查询,利用查询组合sql语句,最后利用 exec执行sql  1行比较简单,一个字符串,第2行是关键,其实是一个查询,结果是行中的值转换成列  在 2 后  print @sql 的效果如下:  Select Name as 姓名,sum(case Subject when '数学' then Result else 0 end) [数学],sum(case Subject when '物理' then Result else 0 end) [物理],sum(case Subject when '英语' then Result else 0 end) [英语],sum(case Subject when '语文' then Result else 0 end) [语文],sum(case Subject when '政治' then Result else 0 end) [政治]  很巧妙的用一个查询组合成了列的值     但是这个sql其实只是一部分,不完整,利用 3行的语句组合一个完整的sql,执行的效果完全正确     继续上面的例子,如果课程,学生,考试成绩单独在一个表中,那就要注意,核心的是上面的列从哪里来的     我们看下面的例子     CREATE TABLE Member  --学生表  (    MID  varchar(10) primary key,  --学生号    MName  varchar(50) NOT NULL  --姓名  )  GO  CREATE TABLE F  --课程表  (   FID   varchar(10) primary key,    --课程号  FName  varchar(50) NOT NULL --课程名  )  GO  CREATE TABLE score  --学生成绩表  (    SID int identity(1,1) primary key,  --成绩记录号    FID varchar(10)  foreign key(FID) references F(FID) ,     --课程号    MID varchar(10)  foreign key(MID) references Member(MID) ,     --学生号    Score  int NOT NULL    --成绩  )    Declare @sql varchar(1000)  Set @sql = 'Select s.mid as 姓名'  Select @sql = @sql + ',sum(case s.FID when '''+score2.FID+''' then s.score else 0 end) ['+score2.FID+']'  from (select distinct FID from score) as score2  --把所有唯一的科目的名称都列举出来    --print @sql  Select @sql = @sql+' from score s group by mid'     Exec (@sql)  这条sql 找到的是学号,课程列显示的是课程号,还有一点不足就是没有考虑到一门课没有考的学生和没有人考过的课程  ,原因很简单, 数据都是从考试成绩表score中得来的  上面的sql 重点注意的是 我起的别名,score2和s,所有的数据的来源 很清晰  完整的考虑到缺考学员以及没有人考过的课程的sql如下:  Declare @sql varchar(8000)  Set @sql = 'Select m.MName as 姓名'  Select @sql = @sql + ',sum(case s.FID when '''+score2.FID+''' then s.score    else 0 end) ['+score2.fname+']'  from (select distinct f.fid, f.fname from score s right join f on (s.fid=f.fid)) as score2  --把所有唯一的科目的名称都列举出来    --print @sql  Select @sql = @sql+' from score s right join member m on(m.mid=s.mid)'    +'    group by m.MName'     Exec (@sql)  
posted on 2009-02-26 15:25  martian6125  阅读(118)  评论(0编辑  收藏  举报