有3个表1、学生表 结构
   学号
   姓名
   ……
2、成绩表
   学号
   科目
   成绩
3、补考成绩表
   学号
   科目
   成绩
   
要求查询的结果
学号  姓名  科目1的成绩  科目2的成绩  科目3的成绩  ……并且要求如果某人某科有补考成绩的就显示此科目补考的成绩

解决方案 »

  1.   

    邹老大的例子:
    常有人提到,用动态生成SQL语句的方法处理数据时,处理语句超长,无法处理的问题
    下面就讨论这个问题:/*-- 数据测试环境 --*/
    if exists (select * from dbo.sysobjects where id = object_id(N'[tb]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [tb]
    GOcreate table tb(单位名称 varchar(10),日期 datetime,销售额 int)
    insert into tb
    select 'A单位','2001-01-01',100
    union all select 'B单位','2001-01-02',101
    union all select 'C单位','2001-01-03',102
    union all select 'D单位','2001-01-04',103
    union all select 'E单位','2001-01-05',104
    union all select 'F单位','2001-01-06',105
    union all select 'G单位','2001-01-07',106
    union all select 'H单位','2001-01-08',107
    union all select 'I单位','2001-01-09',108
    union all select 'J单位','2001-01-11',109/*-- 要求结果
    日期       A单位  B单位 C单位 D单位 E单位  F单位 G单位 H单位 I单位 J单位   
    ---------- ----- ----- ----- ----- ----- ----- ----  ----  ---- ------
    2001-01-01 100   0     0     0     0     0     0     0     0     0
    2001-01-02 0     101   0     0     0     0     0     0     0     0
    2001-01-03 0     0     102   0     0     0     0     0     0     0
    2001-01-04 0     0     0     103   0     0     0     0     0     0
    2001-01-05 0     0     0     0     104   0     0     0     0     0
    2001-01-06 0     0     0     0     0     105   0     0     0     0
    2001-01-07 0     0     0     0     0     0     106   0     0     0
    2001-01-08 0     0     0     0     0     0     0     107   0     0
    2001-01-09 0     0     0     0     0     0     0     0     108   0
    2001-01-11 0     0     0     0     0     0     0     0     0     109
    --*//*-- 常规处理方法*/ 
    declare @sql varchar(8000)
    set @sql='select 日期=convert(varchar(10),日期,120)'
    select @sql=@sql+',['+单位名称
    +']=sum(case 单位名称 when '''+单位名称+''' then 销售额 else 0 end)'
    from(select distinct 单位名称 from tb) a
    exec(@sql+' from tb group by convert(varchar(10),日期,120)')
    /*-- 问题: 如果单位很多,这时,@SQL的值就会被截断,从而出错.*//*--下面给出三种解决办法:--*/--/*-- 方法1. 多个变量处理--定义变量,估计需要多少个变量才能保存完所有数据
    declare @sql0 varchar(8000),@sql1 varchar(8000)
    --,...@sqln varchar(8000)--生成数据处理临时表
    select id=identity(int,0,1),groupid=0
    ,值=',['+单位名称 +']=sum(case 单位名称 when '''
    +单位名称+''' then 销售额 else 0 end)'
    into #temp from(select distinct 单位名称 from tb) a--分组临时表,判断慨最多多少个单位可以组合成一个不超过8000的字符串,这里取假设为5个
    update #temp set groupid=id/5  --5为每组的单位个数--生成SQL语句处理字符串
      --初始化
    select @sql0=''
    ,@sql1=''
    -- ...
    -- ,@sqln  --得到处理字符串
    select @sql0=@sql0+值 from #temp where groupid=0  --第一个变量
    select @sql1=@sql1+值 from #temp where groupid=1  --第二个变量
    --select @sqln=@sqln+值 from #temp where groupid=n  --第n个变量--查询
    exec('select 日期=convert(varchar(10),日期,120)'
    +@sql0+@sql1
    -- ...+@sqln
    +' from tb group by convert(varchar(10),日期,120)
    ')--删除临时表
    drop table #temp/*
    优点:比较灵活,数据量大时只需要增加变量就行了.不用改动其他部分
    缺点:要自行估计处理的数据,估计不足就会出错
    */
    --*/
    --/*--方法2. bcp+isql--因为要用到bcp+isql,所以需要这些信息
    declare @servername varchar(250),@username varchar(250),@pwd varchar(250)
    select @servername='zj'  --服务器名
    ,@username=''    --用户名
    ,@pwd=''     --密码declare @tbname varchar(50),@sql varchar(8000)--创建数据处理临时表
    set @tbname='[##temp_'+convert(varchar(40),newid())+']'
    set @sql='create table '+@tbname+'(值 varchar(8000))
    insert into '+@tbname+' values(''create view '
    +stuff(@tbname,2,2,'')+' as 
    select 日期=convert(varchar(10),日期,120)'')'
    exec(@sql)set @sql='insert into '+@tbname+'
    select '',[''+单位名称+'']=sum(case 单位名称 when ''''''
    +单位名称+'''''' then 销售额 else 0 end)''
    from(select distinct 单位名称 from tb) a'
    exec(@sql)set @sql='insert into '+@tbname+' 
    values(''from tb group by convert(varchar(10),日期,120)'')'
    exec(@sql)--生成创建视图的文件,注意使用了文件:c:\temp.txt
    set @sql='bcp "'+@tbname+'" out "c:\temp.txt" /S"'
    +@servername+'" /U"'+@username+'" /P"'+@pwd+'" /c'
    exec master..xp_cmdshell @sql--删除临时表
    set @sql='drop table '+@tbname
    exec(@sql)--调用isql生成数据处理视图
    set @tbname=stuff(@tbname,2,2,'')
    set @sql='isql /S"'+@servername
    +case @username when '' then '" /E' else '" /U"'+@username+'" /P"'+@pwd+'"' end
    +' /d"'+db_name()+'" /i"c:\temp.txt"'exec master..xp_cmdshell @sql--调用视图,显示处理结果
    set @sql='select * from '+@tbname+'
    drop view '+@tbname
    exec(@sql)/*
    优点:程序自动处理,不存在判断错误的问题
    缺点:复杂,经过的步骤多,容易出错,而且需要一定的操作员权限
    */
    --*/
    --/*-- 方法3. 多个变量处理,综合了方法1及方法2的优点, 解决了方法1中需要人为判断的问题,自动根据要处理的数据量进行变量定义,同时又避免了方法2的繁琐declare @sqlhead varchar(8000),@sqlend varchar(8000)
    ,@sql1 varchar(8000),@sql2 varchar(8000),@sql3 varchar(8000),@sql4 varchar(8000)
    ,@i int,@ic varchar(20)--生成数据处理临时表
    select id=identity(int,0,1),gid=0
    ,a=',['+单位名称 +']=sum(case 单位名称 when '''
    +单位名称+''' then 销售额 else 0 end)'
    into # from(select distinct 单位名称 from tb) a--判断需要多少个变量来处理
    select @i=max(len(a)) from #
    print @i
    set @i=7800/@i--分组临时表
    update # set gid=id/@i
    select @i=max(gid) from #--生成数据处理语句
    select @sqlhead='''select 日期=convert(varchar(10),日期,120)'''
    ,@sqlend=''' from tb group by convert(varchar(10),日期,120)'''
    ,@sql1='',@sql2='select ',@sql3='',@sql4=''while @i>=0
    select @ic=cast(@i as varchar),@i=@i-1
      ,@sql1='@'+@ic+' varchar(8000),'+@sql1
      ,@sql2=@sql2+'@'+@ic+'='''','
      ,@sql3='select @'+@ic+'=@'+@ic+'+a from # where gid='+@ic
       +char(13)+@sql3
      ,@sql4=@sql4+',@'+@icselect @sql1='declare '+left(@sql1,len(@sql1)-1)+char(13)
    ,@sql2=left(@sql2,len(@sql2)-1)+char(13)
    ,@sql3=left(@sql3,len(@sql3)-1)
    ,@sql4=substring(@sql4,2,8000)--执行
    exec( @sql1+@sql2+@sql3+'
    exec('+@sqlhead+'+'+@sql4+'+'+@sqlend+')'
    )--删除临时表
    drop table #
    --*/
    方法3中,关键要做修改的是下面两句,其他基本上不用做改变:--生成数据处理临时表,修改a=后面的内容为相应的处理语句
    select id=identity(int,0,1),gid=0
    ,a=',['+code+']=sum(case b.c_code when '''
    +code+''' then b.value else 0 end)'
    into # from #Class--生成数据处理语句,将@sqlhead,@sqlend赋值为相应的处理语句头和尾
    select @sqlhead='''select a.id,a.name,a.code'''
    ,@sqlend=''' from #Depart a,#Value b where a.Code=b.d_Code group by a.id,a.code,a.name'''
    ,@sql1='',@sql2='select ',@sql3='',@sql4=''
      

  2.   

    gaojier1000你可能没看到我的最后要求吧,就是如果在补考表中有补考成绩的,他那科的最后成绩就是补考的,此外我想使用sql实现查询
      

  3.   

    declare @sql varchar(8000)
    set @sql='select a.学号,a.姓名'
    select @sql=@sql+',['+科目
    +'的成绩]=sum(case b.科目 when '''+科目+''' then case when c.学号 is not null then c.成绩 else b.成绩 end else 0 end)'
    from 成绩表
    group by 科目exec(@sql+' from 学生表 a inner join 成绩表 b on a.学号=b.学号 left join 补考成绩表 c on a.学号=c.学号 and b.科目=c.科目 group by a.学号,a.姓名')
      

  4.   

    海阔天空大侠我忘了说了,我想要的sql语句是这种类型的select a.学号 , a.姓名 , …… from a,b 类型的
      

  5.   

    Create table #stu
    (id int,name varchar(10))
    insert into #stu
    select '01',   '驪' union all
    select '02',   '李' union all
    select '03',   '王'create table #chenji
    (id int,kemu varchar(10),chenji int)
    insert into #chenji
    select 01,  '數學',  80  union all
    select 01,  '語文',  70 union all
    select 01,  '物理',  50 union all
    select 02,  '數學',  80 union all
    select 02,  '語文',  70 union all 
    select 02,  '物理',  88 union all
    select 03,  '語文',  100 union all
    select 03,  '數學',  100 union all
    select 03,  '物理',  100
    create table #bukao
    ( id int,kemu varchar(10),chenji int)
    insert into #bukao
    select 01,  '物理',   66
    select id,name,sum(case when kemu='數學' then chenji else 0 end)as '數學',
                   sum(case when kemu='語文' then chenji else 0 end)as '語文',
                   sum(case when kemu='物理' then chenji else 0 end)as '物理'
    from 
    (
    select c.name, a.id,a.kemu,chenji=case when a.id=b.id and a.kemu=b.kemu then b.chenji else a.chenji end
    from #chenji a left join #bukao b on a.id=b.id and a.kemu=b.kemu
                   left join #stu c on a.id=c.id 
    )a
    group by id,name
    order by idid          name       數學          語文          物理          
    ----------- ---------- ----------- ----------- ----------- 
    1           驪          80          70          66
    2           李          80          70          88
    3           王          100         100         100(3 row(s) affected)
      

  6.   


    select c.name, a.id,a.kemu,chenji=case when a.id=b.id and a.kemu=b.kemu then b.chenji else a.chenji end
    into #t
    from #chenji a left join #bukao b on a.id=b.id and a.kemu=b.kemu
                   left join #stu c on a.id=c.id declare @s varchar(1000)
    set @s='select id,name '
    select @s=@s+',sum(case when kemu='''+kemu+''' then chenji else 0 end)as '''+kemu+''''
    from #t group by kemu
    select @s=@s+' from #t group by id,name order by id'
    exec(@s)id          name       物理          語文          數學          
    ----------- ---------- ----------- ----------- ----------- 
    1           驪          66          70          80
    2           李          88          70          80
    3           王          100         100         100
      

  7.   

    易理解的:
    select A.学号,a.姓名,(case when b2.成绩 is null then b.成绩 else b2.成绩 end) 数学,
    (case when c2.成绩 is null then c.成绩 else c2.成绩 end) 语文,
    (case when d2.成绩 is null then d.成绩 else d2.成绩 end) 物理 from  学生表 a 
    left join (select * from 成绩表 where 科目='数学') b on a.学号=b.学号
    left join (select * from 成绩表 where 科目='语文') c on a.学号=c.学号
    left join (select * from 成绩表 where 科目='物理') d on a.学号=d.学号
    left join (select * from 补考成绩表 where 科目='数学') b2 on a.学号=b2.学号
    left join (select * from 补考成绩表 where 科目='语文') c2 on a.学号=c2.学号
    left join (select * from 补考成绩表 where 科目='物理') d2 on a.学号=d2.学号
      

  8.   

    稍改一下:
    select A.学号,a.姓名,isnull(b2.成绩,b.成绩) 数学,isnull(c2.成绩,c.成绩) 语文,
    isnull(d2.成绩,d.成绩) 物理   from  #学生表 a 
    left join (select * from #成绩表 where 科目='数学') b on a.学号=b.学号
    left join (select * from #成绩表 where 科目='语文') c on a.学号=c.学号
    left join (select * from #成绩表 where 科目='物理') d on a.学号=d.学号
    left join (select * from #补考成绩表 where 科目='数学') b2 on a.学号=b2.学号
    left join (select * from #补考成绩表 where 科目='语文') c2 on a.学号=c2.学号
    left join (select * from #补考成绩表 where 科目='物理') d2 on a.学号=d2.学号
      

  9.   

    那你还要这样的:select a.学号 , a.姓名 , …… from a,b 类型的?
    用动态的吧
      

  10.   

    tscc_ts() ( ) 信誉:100  2007-09-07 15:44:36  得分: 0  
     
     
       大家都有一点忽视了,科目不是死的,是灵活的,只要在表中就可以
      
     
    -------------
    這樣的話,就要用到我上面寫的動態語句了
      

  11.   

    使用系统的数据字典获取你要查询的动态字段,然后动态生成SQL就可以了
      

  12.   

    declare @sql as varchar(8000), @str as varchar(1000)
    set @str=''
    select @str=@str+'sum (case when Course = ' + ''''+Course+'''' +'then Grade else 0 end )'+''''+Course +''''+ ',' from (select distinct Course from grade)a
    select @sql ='select No,'+left(@str,len(@str)-1) +' from grade group by No'
    exec(@sql)