当前位置:奇幻城娱乐网址 > 疾病 > 行转列问题总结,字符串不能超过8000的方法

行转列问题总结,字符串不能超过8000的方法

文章作者:疾病 上传时间:2019-12-03

select 身份证号码,
MAX(t.单位编号) 单位编号,
MAX(t.姓名) 姓名,
MAX(case when t.rows=1 then convert(varchar(max),疾病名称) end) 疾病1,
MAX(case when t.rows=2 then convert(varchar(max),疾病名称) end) 疾病2,
MAX(t.单位名称) 单位名称,
MAX(t.医院编码) 医院编码,
MAX(t.医院名称) 医院名称,
MAX(t.人员类别) 人员类别,
max(t.性别) 性别
from(select
ROW_NUMBER() over(partition by 身份证号码 order by 姓名) as rows,
case
when len(身份证号码) = 15 and cast(substring(身份证号码,15,1) as int) % 2 = 0 then '女'
when len(身份证号码) = 15 and cast(substring(身份证号码,15,1) as int) % 2 = 1 then '男'
when len(身份证号码) = 18 and cast(substring(身份证号码,17,1) as int) % 2 = 0 then '女'
when len(身份证号码) = 18 and cast(substring(身份证号码,17,1) as int) % 2 = 1 then '男'
else null end as 性别,*

经常有人提到,用动态生成SQL语句的方法处理数据时,处理语句超长,无法处理的问题  

行转列问题总结

  1奇幻城游戏 1---流动人员号自动编号函数,由区域代码-年月日-序列号组成的 每日新序号
奇幻城游戏,  2奇幻城游戏 2---geovindu@163.com 涂聚文 www.dusystem.com
  3奇幻城游戏 3if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[GetDayFloatingID]') and xtype in (N'FN', N'IF', N'TF'))
  4奇幻城游戏 4drop function [dbo].[GetDayFloatingID]
  5奇幻城游戏 5GO
  6奇幻城游戏 6CREATE FUNCTION GetDayFloatingID(@headStr nvarchar(10),@date datetime)
  7奇幻城游戏 7RETURNS nvarchar(50)
  8奇幻城游戏 8BEGIN
  9奇幻城游戏 9declare  @oid2 nvarchar(50)
 10奇幻城游戏 10declare @oid nvarchar(50)
 11奇幻城游戏 11declare @day nvarchar(2)
 12奇幻城游戏 12declare @month nvarchar(2)
 13奇幻城游戏 13declare @year nvarchar(4)
 14奇幻城游戏 14declare @ym nvarchar(8)
 15奇幻城游戏 15set @day=day(@date)
 16奇幻城游戏 16if len(@day)=1
 17奇幻城游戏 17    set @day='0'+@day --使日为两位长
 18奇幻城游戏 18set @month=month(@date)
 19奇幻城游戏 19if len(@month)=1
 20奇幻城游戏 20    set @month='0'+@month --使月为两位长
 21奇幻城游戏 21--set @year=right(convert(nvarchar,year(@date)),2)
 22奇幻城游戏 22set @year=convert(nvarchar,year(@date))
 23奇幻城游戏 23set @ym=@year+@month+@day --组成年月日字符
 24奇幻城游戏 24
 25奇幻城游戏 25--格式BJ200808200001
 26奇幻城游戏 26if exists(select * from Populations)
 27奇幻城游戏 27begin
 28奇幻城游戏 28    select  top 1 @oid2=FloatingID from Populations  order by FloatingID desc --获取最后一条的编号,一定要有id,并且自动生成的,倒排序
 29奇幻城游戏 29end
 30奇幻城游戏 30else
 31奇幻城游戏 31begin
 32奇幻城游戏 32    set @oid2=@headStr+@ym+'00000' --没有记录是默认为今天
 33奇幻城游戏 33end
 34奇幻城游戏 34
 35奇幻城游戏 35--流水号不是本月的,重新开始一个新的流水号
 36奇幻城游戏 36if convert(nvarchar,left(@oid2,6))<>@headStr+@ym
 37奇幻城游戏 37begin
 38奇幻城游戏 38--用本月的年月号开始
 39奇幻城游戏 39    set @oid2=@headStr+@ym+'00000'
 40奇幻城游戏 40end
 41奇幻城游戏 41
 42奇幻城游戏 42declare @str nvarchar(50) --临时流水号
 43奇幻城游戏 43
 44奇幻城游戏 44set @str=convert(nvarchar,(convert(int,right(@oid2,4))+1)) --流水号加一
 45奇幻城游戏 45while (5-len(@str)>0)
 46奇幻城游戏 46begin
 47奇幻城游戏 47     set @str='0'+@str    
 48奇幻城游戏 48end
 49奇幻城游戏 49set @oid2=@headStr+@ym+@str
 50奇幻城游戏 50--print @oid2
 51奇幻城游戏 51
 52奇幻城游戏 52--如果该流水号已经存在,则重新获取
 53奇幻城游戏 53while exists(select * from Populations where FloatingID=@oid2)
 54奇幻城游戏 54begin
 55奇幻城游戏 55    
 56奇幻城游戏 56    set @str=convert(nvarchar,(convert(int,right(@oid2,5))+1)) --流水号加一
 57奇幻城游戏 57    while (5-len(@str)>0)
 58奇幻城游戏 58    begin
 59奇幻城游戏 59         set @str='0'+@str    
 60奇幻城游戏 60    end
 61奇幻城游戏 61    set @oid2=@headStr+@ym+@str
 62奇幻城游戏 62--     print @oid2
 63奇幻城游戏 63end
 64奇幻城游戏 64
 65奇幻城游戏 65set @oid=convert(nvarchar,@oid2)
 66奇幻城游戏 66--print 'UL'+convert(nvarchar,year(getdate()))+convert(nvarchar,month(getdate()))+@str
 67奇幻城游戏 67RETURN @oid
 68奇幻城游戏 68END
 69奇幻城游戏 69GO
 70奇幻城游戏 70--测试
 71奇幻城游戏 71DECLARE @S varchar(30)
 72奇幻城游戏 72select @S=dbo.GetDayFloatingID('02',getdate())
 73奇幻城游戏 73select @s as '流动编号'
 74奇幻城游戏 74
 75奇幻城游戏 75--按月自动增长
 76奇幻城游戏 76--如果当月,没有记录号,开始创建,如果有,在此基此上加1,以月新增长序列号
 77奇幻城游戏 77if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[GetMonthFloatingID]') and xtype in (N'FN', N'IF', N'TF'))
 78奇幻城游戏 78drop function [dbo].[GetMonthFloatingID]
 79奇幻城游戏 79GO
 80奇幻城游戏 80CREATE FUNCTION GetMonthFloatingID(@headStr nvarchar(10),@idate datetime)
 81奇幻城游戏 81RETURNS nvarchar(50)
 82奇幻城游戏 82BEGIN
 83奇幻城游戏 83--@idate datetime,@headStr varchar(10),
 84奇幻城游戏 84declare @fid varchar(100),@dat varchar(20),@ym varchar(20),@str nvarchar(50),@olde varchar(30),@y varchar(10),@m varchar(10),@d varchar(10)
 85奇幻城游戏 85--set @headStr='01'
 86奇幻城游戏 86--set @idate=cast('2009-04-3' as datetime)              --getdate()
 87奇幻城游戏 87--set @ym=cast(getdate() as varchar(30))
 88奇幻城游戏 88--找到当月最大的值
 89奇幻城游戏 89select top 1 @fid=FloatingID from Populations 
 90奇幻城游戏 90     where month(cast(substring(FloatingID,3,8) as datetime))=month(@idate) and year(cast(substring(FloatingID,3,8) as datetime))=year(@idate)
 91奇幻城游戏 91    order by substring(FloatingID,11,5) desc
 92奇幻城游戏 92--select @fid=MAX(substring(FloatingID,11,5)) from Populations  
 93奇幻城游戏 93  -- where  month(getdate())
 94奇幻城游戏 94               set @y=cast(year(@idate) as varchar(10))  --
 95奇幻城游戏 95                set @m=cast(month(@idate) as varchar(10))
 96奇幻城游戏 96                   if len(@m)=1
 97奇幻城游戏 97            set @m='0'+@m
 98奇幻城游戏 98        set @d=cast(day(@idate) as varchar(10))
 99奇幻城游戏 99            if len(@d)=1
100奇幻城游戏 100                set @d='0'+@d
101奇幻城游戏 101                 set @ym=@y+@m+@d
102奇幻城游戏 102if @fid<>''
103奇幻城游戏 103   --加一
104奇幻城游戏 104    begin
105奇幻城游戏 105
106奇幻城游戏 106        select @str=convert(nvarchar,(convert(int,right(@fid,5))+1))
107奇幻城游戏 107                while (5-len(@str)>0)
108奇幻城游戏 108        begin
109奇幻城游戏 109             set @str='0'+@str    
110奇幻城游戏 110        end
111奇幻城游戏 111                set @olde=@headStr+@ym+@str
112奇幻城游戏 112        --select @olde
113奇幻城游戏 113    end
114奇幻城游戏 114else
115奇幻城游戏 115   begin
116奇幻城游戏 116         set @olde=@headStr+@ym+'00000'
117奇幻城游戏 117         --select @olde
118奇幻城游戏 118    --print '2'
119奇幻城游戏 119   end 
120奇幻城游戏 120set @olde=convert(nvarchar,@olde)
121奇幻城游戏 121--print 'UL'+convert(nvarchar,year(getdate()))+convert(nvarchar,month(getdate()))+@str
122奇幻城游戏 122RETURN @olde
123奇幻城游戏 123end
124奇幻城游戏 124GO
125奇幻城游戏 125--测试
126奇幻城游戏 126select dbo.GetMonthFloatingID('09',getdate())
127奇幻城游戏 127
128奇幻城游戏 128---2009-03-04 涂聚文 geovindu@163.com

from
dbo.tablename
)t
group by 身份证号码

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

1、行转列

 

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

---1、最简单的行转列
/*   

 

/*-- 要求结果
日期       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
--*/

问题:假设有张学生成绩表(tb)如下:
姓名 课程 分数
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94

row_number将group by分组中的人员编号 然后使用case when 进行区分两种疾病的人。

/*-- 常规处理方法*/

想变成(得到如下结果):
姓名 语文 数学 物理
李四 74   84   94
张三 74   83   93
*/
--测试用
IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb]
GO
create table tb(姓名 varchar(10) , 课程 varchar(10) , 分数 int)
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)
go

奇幻城游戏 129declare @sql varchar(8000)
奇幻城游戏 130set @sql='select 日期=convert(varchar(10),日期,120)'
奇幻城游戏 131select @sql=@sql+',['+单位名称
奇幻城游戏 132 +']=sum(case 单位名称 when '''+单位名称+''' then 销售额 else 0 end)'
奇幻城游戏 133from(select distinct 单位名称 from tb) a
奇幻城游戏 134exec(@sql+' from tb group by convert(varchar(10),日期,120)')

--SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' from tb group by 姓名'
exec(@sql)
--通过动态构建@sql,得到如下脚本
select 姓名 as 姓名 ,
  max(case 课程 when '语文' then 分数 else 0 end) 语文,
  max(case 课程 when '数学' then 分数 else 0 end) 数学,
  max(case 课程 when '物理' then 分数 else 0 end) 物理
from tb
group by 姓名

/*-- 问题: 如果单位很多,这时,@SQL的值就会被截断,从而出错.*/

--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + '],[' , '') + 课程 from tb group by 课程
set @sql = '[' + @sql + ']'
exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b')
--得到SQL SERVER 2005 静态SQL。
select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b

/*--下面给出种解决办法:--*/

--查询结果
/*
姓名         数学          物理          语文         

--/*-- 方法1. 多个变量处理


 

李四         84          94          74
张三         83          93          74

奇幻城游戏 135--定义变量,估计需要多少个变量才能保存完所有数据
奇幻城游戏 136declare @sql0 varchar(8000),@sql1 varchar(8000)
奇幻城游戏 137--,奇幻城游戏 138@sqln varchar(8000)
奇幻城游戏 139
奇幻城游戏 140--生成数据处理临时表
奇幻城游戏 141select id=identity(int,0,1),groupid=0
奇幻城游戏 142 ,值=',['+单位名称 +']=sum(case 单位名称 when '''
奇幻城游戏 143 +单位名称+''' then 销售额 else 0 end)'
奇幻城游戏 144into #temp from(select distinct 单位名称 from tb) a
奇幻城游戏 145
奇幻城游戏 146--分组临时表,判断慨最多多少个单位可以组合成一个不超过8000的字符串,这里取假设为5个
奇幻城游戏 147update #temp set groupid=id/5  --5为每组的单位个数
奇幻城游戏 148
奇幻城游戏 149--生成SQL语句处理字符串
奇幻城游戏 150  --初始化
奇幻城游戏 151select @sql0=''
奇幻城游戏 152 ,@sql1=''
奇幻城游戏 153-- 奇幻城游戏 154
奇幻城游戏 155-- ,@sqln
奇幻城游戏 156
奇幻城游戏 157  --得到处理字符串
奇幻城游戏 158select @sql0=@sql0+值 from #temp where groupid=0  --第一个变量
奇幻城游戏 159select @sql1=@sql1+值 from #temp where groupid=1  --第二个变量
奇幻城游戏 160--select @sqln=@sqln+值 from #temp where groupid=n  --第n个变量
奇幻城游戏 161
奇幻城游戏 162--查询
奇幻城游戏 163exec('select 日期=convert(varchar(10),日期,120)'
奇幻城游戏 164 +@sql0+@sql1
奇幻城游戏 165-- 奇幻城游戏 166+@sqln
奇幻城游戏 167 +' from tb group by convert(varchar(10),日期,120)
奇幻城游戏 168')
奇幻城游戏 169
奇幻城游戏 170--删除临时表
奇幻城游戏 171drop table #temp
奇幻城游戏 172

(所影响的行数为 2 行)
*/

 

--2 加合计
/*
问题:在上述结果的基础上加平均分,总分,得到如下结果:
姓名 语文 数学 物理 平均分 总分

/*
优点:比较灵活,数据量大时只需要增加变量就行了.不用改动其他部分
缺点:要自行估计处理的数据,估计不足就会出错
*/
--*/


--/*-- 方法2. 多个变量处理,综合了方法1, 解决了方法1中需要人为判断的问题,自动根据要处理的数据量进行变量定义

李四 74   84   94   84.00  252
张三 74   83   93   83.33  250
*/

declare @sqlhead varchar(8000),@sqlend varchar(8000)
 ,@sql1 varchar(8000),@sql2 varchar(8000),@sql3 varchar(8000),@sql4 varchar(8000)
 ,@i int,@ic varchar(20)

--SQL SERVER 2000 静态SQL。
select 姓名 姓名,
  max(case 课程 when '语文' then 分数 else 0 end) 语文,
  max(case 课程 when '数学' then 分数 else 0 end) 数学,
  max(case 课程 when '物理' then 分数 else 0 end) 物理,
  cast(avg(分数*1.0) as decimal(18,2)) 平均分,
  sum(分数) 总分
from tb
group by 姓名

--生成数据处理临时表
select id=identity(int,0,1),gid=0
 ,a=',['+单位名称 +']=sum(case 单位名称 when '''
 +单位名称+''' then 销售额 else 0 end)'
into # from(select distinct 单位名称 from tb) a

--SQL SERVER 2000 动态SQL。
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名'
exec(@sql)

--判断需要多少个变量来处理
select @i=max(len(a)) from #
print @i
set @i=7800/@i

--SQL SERVER 2005 静态SQL。
select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b) m,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名

--分组临时表
update # set gid=id/@i
select @i=max(gid) from #

--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + 课程 from tb group by 课程
exec ('select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b) m ,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名')

--生成数据处理语句
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+',@'+@ic

select @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)

--3、不同数据按照序号转为列,方法基本同 1

--执行
exec( @sql1+@sql2+@sql3+'
exec('+@sqlhead+'+'+@sql4+'+'+@sqlend+')'
)

if object_id('tb1') is not null drop table tb1
go
CREATE table tb1 --数据表
(
cpici varchar(10) not null,
cname varchar(10) not null,
cvalue int null
)
--插入测试数据
INSERT INTO tb1 values('T501','x1',31)
INSERT INTO tb1 values('T501','x1',33)
INSERT INTO tb1 values('T501','x1',5)

--删除临时表
drop table #
--*/

INSERT INTO tb1 values('T502','x1',3)
INSERT INTO tb1 values('T502','x1',22)
INSERT INTO tb1 values('T502','x1',3)

方法2中,关键要做修改的是下面两句,其他基本上不用做改变:

INSERT INTO tb1 values('T503','x1',53)
INSERT INTO tb1 values('T503','x1',44)
INSERT INTO tb1 values('T503','x1',50)
INSERT INTO tb1 values('T503','x1',23)

--生成数据处理临时表,修改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

--在sqlserver2000里需要用自增辅助
alter table tb1 add id int identity
go
declare @s varchar(8000)
set @s='select cpici '
select @s=@s+',max(case when rn='+ltrim(rn)+' then cvalue end) as cvlue'+ltrim(rn)
from (select distinct rn from (select rn=(select count(1) from tb1 where cpici=t.cpici and id<=t.id) from tb1 t)a)t
set @s=@s+' from (select rn=(select count(1) from tb1 where cpici=t.cpici and id<=t.id),* from tb1 t
) t group by cpici'

--生成数据处理语句,将@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=''  

exec(@s)
go
alter table tb1 drop column id

--再2005就可以用row_number
declare @s varchar(8000)
set @s='select cpici '
select @s=@s+',max(case when rn='+ltrim(rn)+' then cvalue end) as cvlue'+ltrim(rn)
from (select distinct rn from (select rn=row_number()over(partition by cpici order by getdate()) from tb1)a)t
set @s=@s+' from (select rn=row_number()over(partition by cpici order by getdate()),* from tb1
) t group by cpici'

exec(@s)

---结果
/*
cpici      cvlue1      cvlue2      cvlue3      cvlue4


T501       31          33          5           NULL
T502       3           22          3           NULL
T503       53          44          50          23
警告: 聚合或其他 SET 操作消除了空值。

(3 行受影响)

*/

--测试用
IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb]
GO
create table tb(电话号码 varchar(15), 通话时长 int ,行业 varchar(10))
insert tb
select '13883633601', 10 ,'餐饮' union all
select '18689704236', 20 ,'物流' union all
select '13883633601', 20 ,'物流' union all
select '13883633601', 20 ,'汽车' union all
select '18689704236', 20 ,'医疗' union all
select '18689704236', 20 ,'it' union all
select '18689704236', 20 ,'汽车' union all
select '13883633601', 50 ,'餐饮'
go

declare @sql varchar(8000)
set @sql='select 电话号码,sum(通话时长) 通话总和'
select @sql=@sql+',max(case when rowid='+ltrim(rowid)+' then 行业 else '''' end) as [行业'+ltrim(rowid)+']'
from (select distinct rowid from (select (select count(distinct 行业) from tb where 电话号码=t.电话号码 and 行业<=t.行业) rowid
from tb t) a) b
set @sql=@sql+' from ( select * , (select count(distinct 行业) from tb where 电话号码=t.电话号码 and 行业<=t.行业) rowid
from tb t ) t group by 电话号码'
exec(@sql)

--结果
/*

(所影响的行数为 8 行)

电话号码            通话总和        行业1        行业2        行业3        行业4       



13883633601     100         餐饮         汽车         物流        
18689704236     80          it         汽车         物流         医疗

(所影响的行数为 2 行)

*/

另一种动态行转列:

if object_id('[tb]') is not null drop table [tb]
go  
create table [tb]([姓名] varchar(1),[部门] varchar(4),[学历] varchar(4),[出生年月] datetime)
insert [tb]
select 'A','后勤','高中','1986-1-1' union all
select 'B','后勤','初中','1984-3-7' union all
select 'C','管理','本科','1987-2-1' union all
select 'D','操作','专科','1976-2-1' union all
select 'E','操作','专科','1943-2-1'  
go

GO
if object_id('GetGroupByCol') is not null drop proc GetGroupByCol
go
create  PROCEDURE [dbo].[GetGroupByCol]
@colm nvarchar(100)
  AS
declare @sql varchar(4000)

set @sql='
declare @sql varchar(8000)
set @sql=''select 部门''
select @sql =@sql+ '', sum(case ltrim('+@colm+') when ''''''+ltrim(' + @colm + ')+'''''' then 1 else 0 end)
[''+ltrim(' + @colm + ')+'']'' from (select distinct '+@colm+' from tb where '+@colm+' is not null) as a
set @sql = @sql + '' from tb group by 部门''
exec(@sql)'

exec(@sql)
GO

exec GetGroupByCol N'学历'
exec GetGroupByCol N'出生年月'
exec GetGroupByCol N'姓名'

/*

(所影响的行数为 5 行)

部门   本科          初中          高中          专科         


操作   0           0           0           2
管理   1           0           0           0
后勤   0           1           1           0

(所影响的行数为 3 行)

部门   02  1 1943 12:00AM 02  1 1976 12:00AM 03  7 1984 12:00AM 01  1 1986 12:00AM 02  1 1987 12:00AM



操作   1                  1                  0                  0                  0
管理   0                  0                  0                  0                  1
后勤   0                  0                  1                  1                  0

(所影响的行数为 3 行)

部门   A           B           C           D           E          


操作   0           0           0           1           1
管理   0           0           1           0           0
后勤   1           1           0           0           0

(所影响的行数为 3 行)
*/

以下可参考的例子

1、普通多表联合

2、多表根据时间 计算序号

3、财务相关

4、根据行数转列

5、根据排序大小转

6、分组排序按序号转

本文来自CSDN博客,转载请标明出处:

本文由奇幻城娱乐网址发布于疾病,转载请注明出处:行转列问题总结,字符串不能超过8000的方法

关键词: