首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

交叉表

2012-02-13 
交叉表,高手进select name,sum(casesubjectwhen数学thensourceelse0end)as数学 ,    sum(casesubjectwhen

交叉表,高手进
select "   name,sum(case   subject   when   '数学 '   then   source   else   0   end)   as   '数学 ',
  
  sum(case   subject   when   '英语 '   then   source   else   0   end)   as   '英语 ',
  
  sum(case   subject   when   '语文 '   then   source   else   0   end)   as   '语文 '
  
  from   test
  
  group   by   name

对于这个sql语句,是固定好是两个列来显示成绩的
但是,如果不确定呢?
有什么方法可以实现不固定列的交叉查询

前提:不用存储过程


[解决办法]
动态SQL语句:
-----------------------------
declare @sql varchar(8000)
set @sql= ' '

select @sql=@sql+ ',[ '+subject+ ']=sum(case subject when ' ' '+subject+ ' ' ' then source else 0 end) '
from test group by subject

set @sql= 'select name '+@sql+ ' from test group by name '

exec(@sql)
[解决办法]
普通行列转换

假设有张学生成绩表(t)如下

Name Subject Result
张三 语文  73
张三 数学  83
张三 物理  93
李四 语文  74
李四 数学  84
李四 物理  94

想变成
姓名 语文 数学 物理
张三 73  83  93
李四 74  84  94

create table #t
(
Name varchar(10) ,
Subject varchar(10) ,
Result int
)

insert into #t(Name , Subject , Result) values( '张三 ', '语文 ', '73 ')
insert into #t(Name , Subject , Result) values( '张三 ', '数学 ', '83 ')
insert into #t(Name , Subject , Result) values( '张三 ', '物理 ', '93 ')
insert into #t(Name , Subject , Result) values( '李四 ', '语文 ', '74 ')
insert into #t(Name , Subject , Result) values( '李四 ', '数学 ', '83 ')
insert into #t(Name , Subject , Result) values( '李四 ', '物理 ', '93 ')

declare @sql varchar(8000)
set @sql = 'select Name as ' + '姓名 '
select @sql = @sql + ' , sum(case Subject when ' ' ' + Subject + ' ' ' then Result end) [ ' + Subject + '] '
from (select distinct Subject from #t) as a
set @sql = @sql + ' from #t group by name '
exec(@sql)

drop table #t

--结果
姓名 数学 物理 语文
---------- ----------- ----------- -----------
李四 83 93 74
张三 83 93 73

----------------------------------------------------
如果上述两表互相换一下:即

姓名 语文 数学 物理
张三 73  83  93
李四 74  84  94

想变成
Name Subject Result
张三 语文  73
张三 数学  83
张三 物理  93
李四 语文  74
李四 数学  84
李四 物理  94

create table #t
(
姓名 varchar(10) ,
语文 int ,
数学 int ,
物理 int
)

insert into #t(姓名 , 语文 , 数学 , 物理) values( '张三 ',73,83,93)
insert into #t(姓名 , 语文 , 数学 , 物理) values( '李四 ',74,84,94)

select 姓名 as Name, '语文 ' as Subject,语文 as Result from #t union
select 姓名 as Name, '数学 ' as Subject,数学 as Result from #t union
select 姓名 as Name, '物理 ' as Subject,物理 as Result from #t
order by 姓名 desc

drop table #t

--结果
Name Subject Result
---------- ------- -----------
张三 数学 83
张三 物理 93
张三 语文 73
李四 数学 84


李四 物理 94
李四 语文 74

(所影响的行数为 6 行)

[解决办法]
在SQL Server 2000里一条SQL语句解决不了动态交叉表的问题,通常的方法是借助动态SQL语句。

[解决办法]
--创建测试环境
create table #t(学号 int,课程 varchar(20),分数 int)

--插入测试数据
insert #t(学号,课程,分数)
select '1 ', '语文 ', '20 ' union all
select '1 ', '数学 ', '20 ' union all
select '2 ', '语文 ', '50 ' union all
select '2 ', '数学 ', '20 ' union all
select '2 ', '自然 ', '20 ' union all
select '1 ', '自然 ', '20 '


--求解过程
declare @sql varchar(8000)
set @sql= 'select 学号 '
select @sql = @sql + ',sum(case 课程 when ' ' ' + convert(varchar(20),课程) + ' ' ' then 分数 else 0 end) as [ ' + convert(varchar(20),课程) + '] '
from (select distinct 课程 from #t) _x
select @sql = @sql + ' from #t group by 学号 '

exec ( @sql)

--删除测试环境
drop table #t

/*--测试结果

学号 数学 语文 自然
----------- ----------- ----------- -----------
1 20 20 20
2 20 50 20
*/


热点排行