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(3000set   @abc   =   ''  select   @abc   =   @abc   +   ',min(   case     when   cno   =   '+  cast(cno   as   varchar(8))   +'   then     score     end   )   as   '''+cname+ '''' from   c  declare   @sql     varchar(3000set   @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 endas apple_amount, (case when fruit='pear' then amount else 0 endas 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(4000SET @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 行受影响)

*/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值