SQL行转列代码

1. SQL行转列代码
-
-
表里面有这么一组数据:

code                price
'MCU0-3'       15
'MCU0-3'       20
'MCU0-3'       22
'MCU3-15'     17
'MCU3-15'     16
'MCU3-15'     -10
'MCU3-15'     50
'MCU3-27'     99
'MCU3-27'     96
'MCU3-27'     54
'MCU3-27'     14
'MCU3-27'     46
'MCU3-27'     86

 

现在需要得到这样的结果:

MCU0-3   MCU3-15  MCU3-27
15              17               99
20              16               96
22              -10              54
null            50               14
null            null             46
null            null             86

 

SQL语句是这样写的:

 SELECT ID = IDENTITY(INT, 1, 1), price into #T1 from [table] where code = 'MCU0-3'
 SELECT ID = IDENTITY(INT, 1, 1), price into #T2  from [table] where code = 'MCU3-15'

 SELECT ID = IDENTITY(INT, 1, 1), price into #T3  from [table] where code = 'MCU3-27'

 select t1.price as MCU0-3, t2.price as MCU3-15,t3.price as MCU3-27 from #T1 t1 FULL OUTER JOIN #T2 t2  on t1.id = t2.id FULL OUTER JOIN #T3 t3  on t2.id = t3.id

 

效率不高,但是这样写比较简单。用游标也能达到效果,但是效率怎么样我没有测试,我想应该不会比这个好多少。

 

 

2.

比如数据库中表内容如下:

id       date    month

001 12      1

001 12      2

001 12      3

001 15     4

001    28    5

001 12    6

001 12      7

001 12      8

001 12      9

001 15     10

001    28    11

001 12    12

002 12      1

003 12      2

004 12      3

005 15     4

006    28    5

007 12    6

008 12      7

009 12      8

010 12      9

011 15     10

012 28    11

013 12    12

 

说说关键代码:

SELECT id as '人员' ,
SUM(CASE month WHEN 1 THEN date ELSE 0 END) AS '1月' ,
SUM(CASE month WHEN 2 THEN date ELSE 0 END) AS '2月' ,
SUM(CASE month WHEN 3 THEN date ELSE 0 END) AS '3月' ,
SUM(CASE month WHEN 4 THEN date ELSE 0 END) AS '4月' ,
SUM(CASE month WHEN 5 THEN date ELSE 0 END) AS '5月' ,
SUM(CASE month WHEN 6 THEN date ELSE 0 END) AS '6月' ,
SUM(CASE month WHEN 7 THEN date ELSE 0 END) AS '7月' ,
SUM(CASE month WHEN 8 THEN date ELSE 0 END) AS '8月' ,
SUM(CASE month WHEN 9 THEN date ELSE 0 END) AS '9月' ,
SUM(CASE month WHEN 10 THEN date ELSE 0 END) AS '10月' ,
SUM(CASE month WHEN 11 THEN date ELSE 0 END) AS '11月' ,
SUM(CASE month WHEN 12 THEN date ELSE 0 END) AS '12月'
FROM stuInfo
GROUP BY ID

主要是用case 来转列,并用分组查询来判断表中的记录

 

 

 

 

常有人提到,在写行转列的功能用动态生成SQL语句的方法处理数据时,处理语句超长,会出现无法处理的问题
下面就讨论这个问题:

/*--   数据测试环境   --*/
if   exists   (select   *   from   dbo.sysobjects   where   id   =   object_id(N '[tb] ')   and   OBJECTPROPERTY(id,   N 'IsUserTable ')   =   1)
drop   table   [tb]
GO

create   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)

/*
优点:程序自动处理,不存在判断错误的问题
缺点:复杂,经过的步骤多,容易出错,而且需要一定的操作员权限
*/
--*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值