sql行列转换,字符串相加

复制代码

if object_id('tb')is not null
drop table tb;

CREATE TABLE [dbo].[tb](
    [name] [varchar](50) NULL,
    [class] [varchar](50) NULL,
    [score] [int] NULL
) ON [PRIMARY]
复制代码
insert into tb values('张三','语文',74)
insert into tb values('张三','数学',83)
insert into tb values('张三','物理',93)
insert into tb values('李四','语文',74)
insert into tb values('李四','数学',84)
insert into tb values('李四','物理',94)
 

使用case ..when..then..else..end

1.静态的

select name ,MAX(case class when N'语文' then score else 0 end) 语文,
MAX(case class when N'数学' then score else 0 end) 数学,
MAX(case class when N'物理' then score else 0 end) 物理,
sum(score) 总分,
cast(avg(score*1.0)as decimal(18,2))平均分
from tb group by name

动态的

declare @sql varchar(8000)
set @sql = 'select name '
select @sql = @sql + ' , max(case class when ''' + class + ''' then score else 0 end) [' + class + ']'//循环调用
from (select distinct class from tb) as a
set @sql = @sql + ' from tb group by name'
print(@sql);
exec(@sql)

使用pivot

静态

select m.*,n.总分,n.平均分
from
(select * from tb pivot(max(score)for class in(语文,数学,物理))a)m,
(select name,sum(score)总分,cast(avg(score*1.0)as decimal(18,2))平均分
from tb
group by name)n
where m.name=n.name

动态

复制代码
declare @sql varchar(8000)
set @sql=''  --初始化变量@sql
select @sql=@sql+','+class from tb group by class--变量多值赋值
--同select @sql = @sql + ','+课程from (select distinct课程from tb)a
set @sql=stuff(@sql,1,1,'')--去掉首个','
set @sql='select m.* , n.总分,n.平均分 from
(select * from (select * from tb) a pivot (max(score) for class in ('+@sql+')) b) m ,
(select name,sum(score)总分, cast(avg(score*1.0) as decimal(18,2))平均分 from tb group by name) n
where m.name= n.name'
print(@sql);
exec(@sql)
复制代码

 stuff用法:

以下示例在第一个字符串 abcdef 中删除从第 2 个位置(字符 b)开始的三个字符,然后在删除的起始位置插入第二个字符串,从而创建并返回一个字符串

SELECT STUFF('abcdef', 2, 3, 'ijklmn'),有点想js中的splice

http://www.cnblogs.com/zhangzt/archive/2010/07/29/1787825.html

http://bbs.csdn.net/topics/330058353

http://www.cnblogs.com/doubleliang/archive/2011/07/06/2098775.html

例子:

有个表Kqjl_Info

有三个字段,sfzh(身份证号,进出时间,进出状态(1进,0出))

计算一个员工是否上班,就看他的进出状态是否有1,0,就是先进,然后再出

最后想输出

就是一个月内这个人上了那几天班

具体sql:

复制代码
 with ta as (select sfzh,kqsj,jczt from Kqjl_Info)
select sfzh,
max(case dd when 1 then jczt else 0 end) d1,
max(case dd when 2 then jczt else 0 end) d2,
max(case dd when 3 then jczt else 0 end) d3,
max(case dd when 4 then jczt else 0 end) d4,
max(case dd when 5 then jczt else 0 end) d5,
max(case dd when 6 then jczt else 0 end) d6,
max(case dd when 7 then jczt else 0 end) d7,
max(case dd when 8 then jczt else 0 end) d8,
max(case dd when 9 then jczt else 0 end) d9,
max(case dd when 10 then jczt else 0 end) d10,
max(case dd when 11 then jczt else 0 end) d11,
max(case dd when 12 then jczt else 0 end) d12,
max(case dd when 13 then jczt else 0 end) d13,
max(case dd when 14 then jczt else 0 end) d14,
max(case dd when 15 then jczt else 0 end) d15,
max(case dd when 16 then jczt else 0 end) d16,
max(case dd when 17 then jczt else 0 end) d17,
max(case dd when 18 then jczt else 0 end) d18,
max(case dd when 19 then jczt else 0 end) d19,
max(case dd when 20 then jczt else 0 end) d20,
max(case dd when 21 then jczt else 0 end) d21,
max(case dd when 22 then jczt else 0 end) d22,
max(case dd when 23 then jczt else 0 end) d23,
max(case dd when 24 then jczt else 0 end) d24,
max(case dd when 25 then jczt else 0 end) d25,
max(case dd when 26 then jczt else 0 end) d26,
max(case dd when 27 then jczt else 0 end) d27,
max(case dd when 28 then jczt else 0 end) d28,
max(case dd when 29 then jczt else 0 end) d29,
max(case dd when 30 then jczt else 0 end) d30,
max(case dd when 31 then jczt else 0 end) d31,
sum(jczt) totalCount
from (select sfzh,dd,jczt=1 from (select sfzh,day(kqsj) as dd,
(select cast(jczt as varchar)+',' from ta where sfzh=a.sfzh and day(kqsj)=day(a.kqsj) 
order by kqsj  for xml path('') ) as zt from ta a group by sfzh,day(kqsj)) as tb 
where tb.zt like '%1,0%') as tc group by sfzh;
复制代码

分析:

 with ta as (select sfzh,kqsj,jczt from Kqjl_Info)
 select sfzh,day(kqsj),(select cast(jczt as varchar)+',' from ta where sfzh=a.sfzh and day(kqsj)=day(a.kqsj) order by kqsj  for xml path('') ) as zt from ta a group by sfzh,day(kqsj) 

再选择有1,0的员工,再行列转换

 

复制代码
 use EntranceVista;
  with ta as ( select a.sfzh,a.kqsj,a.jczt,b.xm,gz=b.gz1,a.qybmm  from Kqjl_Info a join Ry_Info b on a.sfzh=b.sfzh  where  1=1  and a.kqsj<='2015-08-25 23:59:59' and a.kqsj>='2015-07-26 00:00:00' )
 select xh=ROW_NUMBER()over (order  by qybmm,xm ),tt.*,b.xm,b.gz,b.qybmm from ta b join(select aa='',bb='',cc='',dd='',ee='',ff='',gg='',hh='',ii='',jj='',sfzh,totalCount=COUNT(1) from ( select sfzh,day(kqsj) as dd,(select cast(jczt as varchar)+',' from ta where sfzh=a.sfzh and day(kqsj)=day(a.kqsj) order by kqsj  for xml path('') ) as zt from ta a group by sfzh,day(kqsj)) as td where zt like '%1,0%' group by sfzh ) tt  on tt.sfzh=b.sfzh order by b.qybmm,b.xm



select xh=ROW_NUMBER()over (order  by qybmm,xm ),tt.*,b.xm,b.gz,b.qybmm from  ta b join( select sfzh, 
 max(case dd when 1 then jczt else 0 end) d1,
 max(case dd when 2 then jczt else 0 end) d2,
 max(case dd when 3 then jczt else 0 end) d3,
 max(case dd when 4 then jczt else 0 end) d4,max(case dd when 5 then jczt else 0 end) d5,max(case dd when 6 then jczt else 0 end) d6,max(case dd when 7 then jczt else 0 end) d7,max(case dd when 8 then jczt else 0 end) d8,max(case dd when 9 then jczt else 0 end) d9,max(case dd when 10 then jczt else 0 end) d10,max(case dd when 11 then jczt else 0 end) d11,max(case dd when 12 then jczt else 0 end) d12,max(case dd when 13 then jczt else 0 end) d13,max(case dd when 14 then jczt else 0 end) d14,max(case dd when 15 then jczt else 0 end) d15,max(case dd when 16 then jczt else 0 end) d16,max(case dd when 17 then jczt else 0 end) d17,max(case dd when 18 then jczt else 0 end) d18,max(case dd when 19 then jczt else 0 end) d19,max(case dd when 20 then jczt else 0 end) d20,max(case dd when 21 then jczt else 0 end) d21,max(case dd when 22 then jczt else 0 end) d22,max(case dd when 23 then jczt else 0 end) d23,max(case dd when 24 then jczt else 0 end) d24,max(case dd when 25 then jczt else 0 end) d25,max(case dd when 26 then jczt else 0 end) d26,max(case dd when 27 then jczt else 0 end) d27,max(case dd when 28 then jczt else 0 end) d28,max(case dd when 29 then jczt else 0 end) d29,max(case dd when 30 then jczt else 0 end) d30,
 max(case dd when 31 then jczt else 0 end) d31,
 sum(jczt) totalCount  from (
 select sfzh,dd,jczt=1 from (
 select sfzh,day(kqsj) as dd, (
 select cast(jczt as varchar)+',' from ta where sfzh=a.sfzh and day(kqsj)=day(a.kqsj)  order by kqsj  for xml path('') ) as zt 
 from ta a group by sfzh,day(kqsj)) as tb 
  where tb.zt like '%1,0%') as tc group by sfzh ) tt   on tt.sfzh=b.sfzh order by b.qybmm,b.xm
复制代码

 

复制代码
  DBCC DROPCLEANBUFFERS
  --清除buffer pool里的所有缓存数据
 DBCC freeproccache
 GO
  
  --清除buffer pool里的所有缓存的执行计划
  SET STATISTICS TIME ON
  GO
  USE [EntranceVista]
 GO
  with ta as (select sfzh,kqsj,jczt from Kqjl_Info)
 select sfzh,day(kqsj),(select cast(jczt as varchar)+',' from ta where sfzh=a.sfzh and day(kqsj)=day(a.kqsj) order by kqsj  for xml path('') ) as zt from ta a group by sfzh,day(kqsj) 

 GO
 SET STATISTICS TIME OFF
 GO
复制代码

报告:

复制代码
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
SQL Server 分析和编译时间: 
   CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

 SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 分析和编译时间: 
   CPU 时间 = 0 毫秒,占用时间 = 39 毫秒。

(47390 行受影响)

 SQL Server 执行时间:
   CPU 时间 = 15802 毫秒,占用时间 = 18523 毫秒。
复制代码

 http://www.cnblogs.com/doubleliang/archive/2011/07/06/2098775.html

 

posted @   hongdada  阅读(1049)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示