SQL中几种行变列的情况

/*有三个数据库表, 一个是学生表S(SNO,SNAME),字段分别表示学号,姓名; 一个是课程表C(CNO,CNAME),字段分别表示课程号,课程名称; 一个是成绩表T(SNO,CNO,SCORE),字段分别表示学号,课程号,该学生该课程成绩。

现在要实现这个表:

姓名 语文 数学 英语 物理 化学 ... 张三  分数 分数 分数 分数 分数  李四 分数 分数 分数 分数 分数 王五 分数 分数 分数 分数 分数 ...

*/

T-SQL

object_id ( ' s ' is   not   null drop   table  s if   object_id ( ' c ' is   not   null drop   table  c if   object_id ( ' t ' is   not   null drop   table  t create   table  S(sno  int ,sname  varchar ( 300 )) create   table  c(cno  int ,cname  varchar ( 300 )) create   table  t(sno  int ,cno  int ,score  int ) insert     into    S(sno,sname)  select     1 , ' 张三 '   union     select     2 , ' 李四 '   union   select     3 , ' 王五 '   union   select     4 , ' 甲六 '   insert     into    c(cno,cname)  select     1 , ' 语文 '   union     select     2 , ' 数学 '   union   select     3 , ' 英语 '   union     select     4 , ' 物理 '   union     select     5 , ' 化学 '   union   select     6 , ' 历史 '   union   select     7 , ' 历史 '   insert     into    t(SNO,CNO,score)  select     1 , 1 , 80   union   select     1 , 2 , 70   union   select     1 , 3 , 50   union   select     1 , 4 , 60   union   select     1 , 5 , 90   union   select     1 , 6 , 60   union   select     2 , 1 , 41   union   select     2 , 2 , 42   union   select     2 , 3 , 53   union   select     2 , 4 , 64   union   select     3 , 1 , 43   union   select     3 , 2 , 44   union   select     3 , 3 , 55   union   select     3 , 4 , 66   /*使用动态SQL语句*/ declare     @abc     varchar ( 3000 set     @abc     =     ''   select     @abc     =     @abc     +     ' ,min(   case     when   cno   =    ' +    cast (cno    as     varchar ( 8 ))    + '    then     score     end   )   as    ''' + cname +   ''''   from    c  declare     @sql       varchar ( 3000 set     @sql     =     ' select   (select   sname     from   S  where S.sno=   T.sno   )   as   sname      ' + @abc     + '    from   T   group   by   sno '   exec    ( @sql /* 不使用动态SQL语句*/ select  sname 姓名,  max (yw) 语文, max (sx) 数学, max (yy) 英语, max (wl) 物理, max (hx) 化学,  max (ls) 历史 from  (   select  sname ,( case   when  cname = ' 语文 '   then  score   end ) yw,  ( case   when  cname = ' 数学 '   then  score  end ) sx, ( case   when  cname = ' 英语 '   then  score   end ) yy,  ( case   when  cname = ' 物理 '   then  score   end ) wl, ( case   when  cname = ' 化学 '   then  score   end ) hx, ( case   when  cname = ' 历史 '   then  score   end ) ls       from  t  left   join  s  on  t.sno = s.sno  left   join  c  on  t.cno = c.cno   ) tmp    group   by  sname

 

有如图A所示的表stat,表的内容为各个班级拥有水果的数量,要求将表stat的查询结果以图B的形式显示。

class        fruit     amount ----------------------------- class a      apple     30 class a      pear      15 class b      apple     40 class b      pear      20   图 A

class    apple_amount pear_amount ---------------------------- class a      30        15 class b      40        20   图 B

T-SQL

 

create   table  stat(class  varchar ( 30 ), fruit  varchar ( 30 ), amount  int ) insert   into  stat (class,fruit,amount)  select   ' class a ' ' apple ' 30 union select   ' class a ' ' pear ' 15 union select   ' class b ' ' apple ' 40 union select   ' class b ' ' pear ' 20 union select   ' class a ' , ' apple ' , 11   union    select   ' class b ' , ' apple ' , 12 select   *   from  stat select  class,  sum (apple_amount) apple_amount,  sum (pear_amount) pear_amount    from  (      select  class, ( case   when  fruit = ' apple '   then  amount  else   0   end as  apple_amount, ( case   when  fruit = ' pear '   then  amount  else   0   end as  pear_amount      from  stat   ) tmp    group   by  class

 

PL/SQL

 

  create   table  stat(class  varchar2 ( 30 ), fruit  varchar2 ( 30 ), amount  number ( 10 ));   insert   into  stat(class, fruit, amount)   values ( ' class a ' ' apple ' 30 );   insert   into  stat(class, fruit, amount)   values ( ' class a ' ' pear ' 15 );   insert   into  stat(class, fruit, amount)   values ( ' class b ' ' apple ' 40 );   insert   into  stat(class, fruit, amount)   values ( ' class b ' ' pear ' 20 );   commit select  class,  sum (apple_amount) apple_amount,  sum (pear_amount) pear_amount    from  (      select  class, decode(fruit,  ' apple ' , amount,  0 ) apple_amount, decode(fruit,  ' pear ' , amount,  0 ) pear_amount      from  stat   )    group   by  class  

 

存储过程

/*范例表      create   table   表1   (      號數   char(10),        成績   integer,        科目   char(10)   )        insert   into   表1   select   '1',60,'数学'        union   select   '1',43,'物理'        union   select   '1',100,'语文'        union   select   '2',87,'语文'        union   select   '2',99,'数学'        union   select   '2',89,'物理'        union   select   '2',87,'语文'        */        Create     procedure    RowToColumn           @Table     varchar ( 30 ),                      -- 表名           @MasterField     varchar ( 30 ),  -- 待转名称列名   char字段           @SlaveField     varchar ( 30 ),  -- 待转数据列名   int型字段           @GroupID     varchar ( 30 -- 分组ID           as        -- 调用方法   RowToColumn   '表1','科目','成績','號數'         begin            DECLARE     @mSQL     VARCHAR ( 8000 )               set     @msql     =     ' DECLARE   @SQL   VARCHAR(8000) '                set     @msql     =     @msql     +     '    set   @SQL=    '' select    '     +     @GroupID     +     ''''                set     @msql     =     @msql     +     '    SELECT   @SQL=   @SQL+ '' ,max(CASE   WHEN    '     +                @MasterField     +     ' = '''''' + '     +     @MasterField     +     ' + ''''''    then      '     +     @SlaveField     +                    '    else   0   end   )[ '' + '     +     @MasterField     +     ' + '' ] ''    from(select   distinct    '     +                    @MasterField     +     '    from    '     +     @Table     +     ' )   a '                set     @msql     =     @msql     +     '    SET   @SQL=@SQL+    ''    from    '     +     @Table     +     '    group   by    '     +                    @GroupID     +     ''''                set     @msql     =     @msql     +     '    exec(@SQL) '                exec ( @msql )       end      

 

分组行转列

/*1. 表格A原始数据如下:*/ CREATE   TABLE   [ dbo ] . [ A ]  (   [ C1 ]   [ varchar ]  ( 50 ) COLLATE Chinese_PRC_CS_AS  NULL  ,   [ C2 ]   [ varchar ]  ( 50 ) COLLATE Chinese_PRC_CS_AS  NULL  ,   [ C3 ]   [ varchar ]  ( 50 ) COLLATE Chinese_PRC_CS_AS  NULL  ,   [ C4 ]   [ varchar ]  ( 50 ) COLLATE Chinese_PRC_CS_AS  NULL   insert   into  A ( ' 95533 ' , ' SZ ' , ' 44 ' , ' 123000 ' ) insert   into  A ( ' 95566 ' , ' SZ ' , ' 44 ' , ' 233300 ' ) insert   into  A ( ' 95588 ' , ' GZ ' , ' 44 ' , ' 4566 ' ) insert   into  A ( ' 95599 ' , ' GZ ' , ' 44 ' , ' 456666 ' ) insert   into  A ( ' 95533 ' , ' ZH ' , ' 44 ' , ' 333333 ' ) insert   into  A ( ' 95577 ' , ' DG ' , ' 44 ' , ' 555555 ' ) insert   into  A ( ' 95588 ' , ' ST ' , ' 44 ' , ' 44444 ' /*2. 分组行变列 处理数据:*/ DECLARE   @SQL   VARCHAR ( 4000 SET   @SQL = ' SELECT C2 '   SELECT   @SQL =   @SQL +   ' ,max(CASE WHEN C1 =  '''   +  C1  +   '''  THEN C4 ELSE 0 END) [ ' + C1 + ' ] '   FROM  ( SELECT   DISTINCT  C1  FROM  A) TAB SET   @SQL = @SQL +   '  FROM A GROUP BY C2 '   EXEC  ( @SQL /*得到如下结果: */ C2  95533   95566   95577   95588   95599 -- ------------------------------------------ DG  0   0   555555   0   0   GZ  0   0   0   4566   456666   ST  0   0   0   44444   0   SZ  123000   233300   0   0   0   ZH  333333   0   0   0   0   OK, 分组就这样完成了. 参考经典实例:  /*   实例一 create table t (id int identity,name varchar(10),code int) insert t values('人口',20) insert t values('经济',12) insert t values('文化',15) insert t values('土地',45)  declare @sql varchar(1000) set @sql = '' select @sql = @sql+name+'=max(case when name='''+name+''' then code else null end),' from t --print @sql  set @sql = left(@sql,len(@sql) - 1) set @sql = 'select [姓名]=''年龄'', '+@sql+' from t' exec (@sql) --drop table t  实例二  create   table   #(a   varchar(100),b   int)      insert   #   values('aa',11)      insert   #   values('bb',1)      insert   #   values('aa',45)      insert   #   values('cc',81)      insert   #   values('a',11)      insert   #   values('aay',561)      insert   #   values('a',14)           declare   @sql   varchar(8000)      set   @sql   =   'select   '      select   @sql   =   @sql   +   'sum(case   a   when   '''+a+'''                                                            then   b   else   0   end)   '+a+'的数量,'          from   (select   distinct   a   from   #)   as   a           select   @sql   =   left(@sql,len(@sql)-1)   +   '   from   #'           exec(@sql)         --  drop   table   #  */  
--行列互转

/******************************************************************************************************************************************************

以学生成绩为例子,比较形象易懂



整理人:中国风(Roy)



日期:2008.06.06

******************************************************************************************************************************************************/



--1、行互列

--> --> (Roy)生成測試數據

 

if not object_id('Class') is null

    drop table Class

Go

Create table Class([Student] nvarchar(2),[Course] nvarchar(2),[Score] int)

Insert Class

select N'张三',N'语文',78 union all

select N'张三',N'数学',87 union all

select N'张三',N'英语',82 union all

select N'张三',N'物理',90 union all

select N'李四',N'语文',65 union all

select N'李四',N'数学',77 union all

select N'李四',N'英语',65 union all

select N'李四',N'物理',85 

Go

--2000方法:

动态:



declare @s nvarchar(4000)

set @s=''

Select     @s=@s+','+quotename([Course])+'=max(case when [Course]='+quotename([Course],'''')+' then [Score] else 0 end)'

from Class group by[Course]

exec('select [Student]'+@s+' from Class group by [Student]')





生成静态:



select 

    [Student],

    [数学]=max(case when [Course]='数学' then [Score] else 0 end),

    [物理]=max(case when [Course]='物理' then [Score] else 0 end),

    [英语]=max(case when [Course]='英语' then [Score] else 0 end),

    [语文]=max(case when [Course]='语文' then [Score] else 0 end) 

from 

    Class 

group by [Student]



GO

动态:



declare @s nvarchar(4000)

Select     @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course]

exec('select * from Class pivot (max([Score]) for [Course] in('+@s+'))b')



生成静态:

select * 

from 

    Class 

pivot 

    (max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b



生成格式:

/*

Student 数学          物理          英语          语文

------- ----------- ----------- ----------- -----------

李四      77          85          65          65

张三      87          90          82          78



(2 行受影响)

*/



------------------------------------------------------------------------------------------

go

--加上总成绩(学科平均分)



--2000方法:

动态:



declare @s nvarchar(4000)

set @s=''

Select     @s=@s+','+quotename([Course])+'=max(case when [Course]='+quotename([Course],'''')+' then [Score] else 0 end)'

from Class group by[Course]

exec('select [Student]'+@s+',[总成绩]=sum([Score])  from Class group by [Student]')--加多一列(学科平均分用avg([Score]))



生成动态:



select 

    [Student],

    [数学]=max(case when [Course]='数学' then [Score] else 0 end),

    [物理]=max(case when [Course]='物理' then [Score] else 0 end),

    [英语]=max(case when [Course]='英语' then [Score] else 0 end),

    [语文]=max(case when [Course]='语文' then [Score] else 0 end),

    [总成绩]=sum([Score]) --加多一列(学科平均分用avg([Score]))

from 

    Class 

group by [Student]



go



--2005方法:



动态:



declare @s nvarchar(4000)

Select     @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course] --isnull(@s+',','') 去掉字符串@s中第一个逗号

exec('select [Student],'+@s+',[总成绩] from (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a 

pivot (max([Score]) for [Course] in('+@s+'))b ')



生成静态:



select 

    [Student],[数学],[物理],[英语],[语文],[总成绩] 

from 

    (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a --平均分时用avg([Score])

pivot 

    (max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b 



生成格式:



/*

Student 数学          物理          英语          语文          总成绩

------- ----------- ----------- ----------- ----------- -----------

李四      77          85          65          65          292

张三      87          90          82          78          337



(2 行受影响)

*/



go



--2、列转行

--> --> (Roy)生成測試數據

 

if not object_id('Class') is null

    drop table Class

Go

Create table Class([Student] nvarchar(2),[数学] int,[物理] int,[英语] int,[语文] int)

Insert Class

select N'李四',77,85,65,65 union all

select N'张三',87,90,82,78

Go



--2000:



动态:



declare @s nvarchar(4000)

select @s=isnull(@s+' union all ','')+'select [Student],[Course]='+quotename(Name,'''')--isnull(@s+' union all ','') 去掉字符串@s中第一个union all

+',[Score]='+quotename(Name)+' from Class'

from syscolumns where ID=object_id('Class') and Name not in('Student')--排除不转换的列

order by Colid

exec('select * from ('+@s+')t order by [Student],[Course]')--增加一个排序



生成静态:

select * 

from (select [Student],[Course]='数学',[Score]=[数学] from Class union all 

select [Student],[Course]='物理',[Score]=[物理] from Class union all 

select [Student],[Course]='英语',[Score]=[英语] from Class union all 

select [Student],[Course]='语文',[Score]=[语文] from Class)t 

order by [Student],[Course]



go

--2005:



动态:



declare @s nvarchar(4000)

select @s=isnull(@s+',','')+quotename(Name)

from syscolumns where ID=object_id('Class') and Name not in('Student') 

order by Colid

exec('select Student,[Course],[Score] from Class unpivot ([Score] for [Course] in('+@s+'))b')



go

select 

    Student,[Course],[Score] 

from 

    Class 

unpivot 

    ([Score] for [Course] in([数学],[物理],[英语],[语文]))b



生成格式:

/*

Student Course Score

------- ------- -----------

李四      数学      77

李四      物理      85

李四      英语      65

李四      语文      65

张三      数学      87

张三      物理      90

张三      英语      82

张三      语文      78



(8 行受影响)

*/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值