当前位置: 代码迷 >> SQL >> 在论坛中出现的比较难的sql有关问题:7
  详细解决方案

在论坛中出现的比较难的sql有关问题:7

热度:69   发布时间:2016-05-05 11:58:39.0
在论坛中出现的比较难的sql问题:7
最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。

所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。


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语句,某一行数据变为列名。
http://bbs.csdn.net/topics/390622184?page=1#post-395860916
我有一个表
   日期       合肥   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*/
动态生成的sql语句:
 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 



  相关解决方案