所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。
1、数据查询,行转列的问题。
http://bbs.csdn.net/topics/390621630?page=1#post-395855019
根据数据查询得到如下数据表(tab):
班级 学号 姓名 科目 得分 班排名 校排名 标准分
ClassName Code Name SubjectName TotalScore ClassRank SchoolRank TValue
201班 101 张三 语文 95 1 1 700
201班 102 李四 语文 83 2 3 600
202班 201 张飞 语文 85 1 2 700
202班 202 赵云 语文 75 2 4 600
201班 101 张三 数学 83 2 2 600
201班 102 李四 数学 85 1 3 700
202班 201 张飞 数学 95 1 1 700
202班 202 赵云 数学 80 2 4 600
需要得到如下数据:
班级 学号 姓名 语文 得分 班排名 校排名 标准分 数学 得分 班排名 校排名 标准分
201班 101 张三 语文 95 1 1 700 数学 83 2 2 600
201班 102 李四 语文 83 2 3 600 数学 85 1 3 700
202班 201 张飞 语文 85 1 2 700 数学 95 1 1 700
202班 202 赵云 语文 75 2 4 600 数学 80 2 4 600
真心求SQL,或者实现方法。
科目是动态的。能实现静态转换也行。
真心谢谢。
我的解法:
if object_id('tab') is not null drop table tabgo create table tab([班级] varchar(9),[学号] varchar(4),[姓名] varchar(4),[科目] varchar(11),[得分] varchar(10),[班排名] varchar(9),[校排名] varchar(10),[标准分] varchar(6))insert tabselect '201班','101','张三','语文','95','1','1','700' union allselect '201班','102','李四','语文','83','2','3','600' union allselect '202班','201','张飞','语文','85','1','2','700' union allselect '202班','202','赵云','语文','75','2','4','600' union allselect '201班','101','张三','数学','83','2','2','600' union allselect '201班','102','李四','数学','85','1','3','700' union allselect '202班','201','张飞','数学','95','1','1','700' union allselect '202班','202','赵云','数学','80','2','4','600'--------------开始查询--------------------------declare @sql nvarchar(3000);set @sql = '';select @sql = @sql + ',min(case when 科目=''' + 科目 + ''' then 科目 else null end) as ['+科目+ ']'+ ',min(case when 科目=''' + 科目 + ''' then 得分 else null end) as 得分' + ',min(case when 科目=''' + 科目 + ''' then 班排名 else null end) as 班排名'+ ',min(case when 科目=''' + 科目 + ''' then 校排名 else null end) as 校排名'+ ',min(case when 科目=''' + 科目 + ''' then 标准分 else null end) as 标准分' from tabgroup by 科目order by 科目 descselect @sql = 'select 班级,学号,姓名'+@sql + ' from tab group by 班级,学号,姓名'select @sql exec(@sql) /*班级 学号 姓名 语文 得分 班排名 校排名 标准分 数学 得分 班排名 校排名 标准分--------- ---- ---- ----------- ---------- --------- ---------- ------ ----------- ---------- --------- ---------- ------201班 101 张三 语文 95 1 1 700 数学 83 2 2 600201班 102 李四 语文 83 2 3 600 数学 85 1 3 700202班 201 张飞 语文 85 1 2 700 数学 95 1 1 700202班 202 赵云 语文 75 2 4 600 数学 80 2 4 600警告: 聚合或其他 SET 操作消除了 Null 值。*/
上面语句,产生的动态语句:
select 班级,学号,姓名, min(case when 科目='语文' then 科目 else null end) as [语文], min(case when 科目='语文' then 得分 else null end) as 得分, min(case when 科目='语文' then 班排名 else null end) as 班排名, min(case when 科目='语文' then 校排名 else null end) as 校排名, min(case when 科目='语文' then 标准分 else null end) as 标准分, min(case when 科目='数学' then 科目 else null end) as [数学], min(case when 科目='数学' then 得分 else null end) as 得分, min(case when 科目='数学' then 班排名 else null end) as 班排名, min(case when 科目='数学' then 校排名 else null end) as 校排名, min(case when 科目='数学' then 标准分 else null end) as 标准分 from tab group by 班级,学号,姓名
2、sql语句,某一行数据变为列名。
我有一个表
日期 合肥 F3 F4 芜湖 F6 F7
--------------------------------------------------------------------
NULL 气象 最高 最低 气象 最高 最低
2013-10 多云 32 20 雨 35 20
2013-11 晴 30 20 晴 25 20
现在要变为:
日期 城市 气象 最高 最低
--------------------------------------------------------------
2013-10 合肥 多云 32 20
2013-10 芜湖 雨 35 20
2013-11 合肥 晴 30 20
2013-11 芜湖 晴 25 20
可以的话尽量写成动态,因为不只两个城市
如果我的第一个表是这样呢:
日期 合肥 F3 F4 芜湖 F6 F7 北京 F9 F10 福州 F12 F13
------------------------------------------------------------------------------------------------
NULL 气象 最高 最低 气象 最高 最低 气象 最高 最低 气象 最高 最低
2013-10 多云 32 20 雨 35 20 晴 32 20 多云 25 20
2013-11 晴 30 20 晴 25 20 雨 31 21 晴 25 21
你能否写一个循环语句,首先城市的数量是(最后一个列名的阿拉伯数字-1)/3,然后再作判断写出像你第一个贴得出的结果集。
if object_id('tb') is not null drop table tbgocreate table tb(日期 varchar(15),合肥 varchar(10),F3 varchar(10),F4 varchar(10),芜湖 varchar(10),F6 varchar(10),F7 varchar(10),北京 varchar(10),F9 varchar(10),F10 varchar(10),福州 varchar(10),F12 varchar(10),F13 varchar(10))insert into tbselect NULL,'气象', '最高','最低','气象','最高','最低','气象','最高','最低' ,'气象','最高','最低' union allselect '2013-10','多云', '32' ,'20', '雨','35', '20', '晴','32','20' , '多云','25','20' union allselect '2013-11','晴', '30','20','晴','25', '20', '雨','31','21','晴','25' , '21' godeclare @tb_name nvarchar(100);declare @t table(tb_name nvarchar(100),column_name nvarchar(100),column_id int) declare @i intdeclare @count intdeclare @sql nvarchar(max);--这里的表为 tb,需要换成你自己的表名set @tb_name = 'tb'insert into @tselect t.name , c.name, c.column_idfrom sys.tables tinner join sys.columns c on t.object_id = c.object_idwhere t.name = @tb_name set @i = 2set @count = (select count(*) from @t)set @sql ='';while @i < @countbegin set @sql = @sql + 'union all select 日期,''' + (select column_name from @t where column_id = @i) + ''' as 城市,' + (select column_name from @t where column_id = @i) + ' as 气象,' + (select column_name from @t where column_id = @i+1) + ' as 最高,'+ (select column_name from @t where column_id = @i+1+1) + ' as 最低 ' + ' from ' + (select distinct tb_name from @t) + ' where 日期 is not null ' set @i = @i + 3endselect @sql = stuff(@sql,1,len('union all'),'')--select @sqlexec(@sql)/*日期 城市 气象 最高 最低--------------- ---- ---------- ---------- ----------2013-10 合肥 多云 32 202013-11 合肥 晴 30 202013-10 芜湖 雨 35 202013-11 芜湖 晴 25 202013-10 北京 晴 32 202013-11 北京 雨 31 212013-10 福州 多云 25 202013-11 福州 晴 25 21*/
select 日期,'合肥' as 城市,合肥 as 气象,F3 as 最高,F4 as 最低 from tb where 日期 is not null union all select 日期,'芜湖' as 城市,芜湖 as 气象,F6 as 最高,F7 as 最低 from tb where 日期 is not null union all select 日期,'北京' as 城市,北京 as 气象,F9 as 最高,F10 as 最低 from tb where 日期 is not null union all select 日期,'福州' as 城市,福州 as 气象,F12 as 最高,F13 as 最低 from tb where 日期 is not null