还有十四行四列由于空间所限就没有列进来,以四行四列作例,希望能有一个通用的转换语句
项目                            2006.4.28 2006.8.19 2007.3.19 2007.05.19
---------------------------------------------------------------------------------------------
活期存款                                  0.72      0.72      0.72       0.72
整存整取(三个月)                      1.71       1.8      1.98       2.07
整存整取(半年)                      2.07      2.25      2.43       2.61
整存整取(一年)                      2.25      2.52      2.79       3.06转变成结果
日期                            活期存款   整存整取(三个月) 整存整取(半年) 整存整取(一年)
---------------------------------------------------------------------------------------------
2006.4.28                                0.72      1.71      2.07       2.25
2006.8.19                      0.72       1.8      2.25       2.52
2007.3.19                      0.72      1.98      2.43       2.79
2007.05.19                      0.72      2.07      2.61       3.06

解决方案 »

  1.   

    普通行列转换
    问题:假设有张学生成绩表(tb)如下:
    姓名 课程 分数
    张三 语文 74
    张三 数学 83
    张三 物理 93
    李四 语文 74
    李四 数学 84
    李四 物理 94
    想变成(得到如下结果): 
    姓名 语文 数学 物理 
    ---- ---- ---- ----
    李四 74   84   94
    张三 74   83   93
    -------------------
    */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--SQL SERVER 2000 静态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 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 SERVER 2005 静态SQL。
    select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b--SQL SERVER 2005 动态SQL。
    declare @sql varchar(8000)
    select @sql = isnull(@sql + ',' , '') + 课程 from tb group by 课程
    exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b')---------------------------------/*
    问题:在上述结果的基础上加平均分,总分,得到如下结果:
    姓名 语文 数学 物理 平均分 总分 
    ---- ---- ---- ---- ------ ----
    李四 74   84   94   84.00  252
    张三 74   83   93   83.33  250
    */--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 姓名--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) --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.姓名--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.姓名')drop table tb    ------------------
    ------------------/*
    问题:如果上述两表互相换一下:即表结构和数据为:
    姓名 语文 数学 物理
    张三 74  83  93
    李四 74  84  94
    想变成(得到如下结果): 
    姓名 课程 分数 
    ---- ---- ----
    李四 语文 74
    李四 数学 84
    李四 物理 94
    张三 语文 74
    张三 数学 83
    张三 物理 93
    --------------
    */create table tb(姓名 varchar(10) , 语文 int , 数学 int , 物理 int)
    insert into tb values('张三',74,83,93)
    insert into tb values('李四',74,84,94)
    go--SQL SERVER 2000 静态SQL。
    select * from
    (
    select 姓名 , 课程 = '语文' , 分数 = 语文 from tb 
    union all
    select 姓名 , 课程 = '数学' , 分数 = 数学 from tb
    union all
    select 姓名 , 课程 = '物理' , 分数 = 物理 from tb
    ) t
    order by 姓名 , case 课程 when '语文' then 1 when '数学' then 2 when '物理' then 3 end--SQL SERVER 2000 动态SQL。
    --调用系统表动态生态。
    declare @sql varchar(8000)
    select @sql = isnull(@sql + ' union all ' , '' ) + ' select 姓名 , [课程] = ' + quotename(Name , '''') + ' , [分数] = ' + quotename(Name) + ' from tb'
    from syscolumns 
    where name! = N'姓名' and ID = object_id('tb') --表名tb,不包含列名为姓名的其它列
    order by colid asc
    exec(@sql + ' order by 姓名 ')--SQL SERVER 2005 动态SQL。
    select 姓名 , 课程 , 分数 from tb unpivot (分数 for 课程 in([语文] , [数学] , [物理])) t--SQL SERVER 2005 动态SQL,同SQL SERVER 2000 动态SQL。--------------------
    /*
    问题:在上述的结果上加个平均分,总分,得到如下结果:
    姓名 课程   分数
    ---- ------ ------
    李四 语文   74.00
    李四 数学   84.00
    李四 物理   94.00
    李四 平均分 84.00
    李四 总分   252.00
    张三 语文   74.00
    张三 数学   83.00
    张三 物理   93.00
    张三 平均分 83.33
    张三 总分   250.00
    ------------------
    */select * from
    (
    select 姓名 as 姓名 , 课程 = '语文' , 分数 = 语文 from tb 
    union all
    select 姓名 as 姓名 , 课程 = '数学' , 分数 = 数学 from tb
    union all
    select 姓名 as 姓名 , 课程 = '物理' , 分数 = 物理 from tb
    union all
    select 姓名 as 姓名 , 课程 = '平均分' , 分数 = cast((语文 + 数学 + 物理)*1.0/3 as decimal(18,2)) from tb
    union all
    select 姓名 as 姓名 , 课程 = '总分' , 分数 = 语文 + 数学 + 物理 from tb
    ) t
    order by 姓名 , case 课程 when '语文' then 1 when '数学' then 2 when '物理' then 3 when '平均分' then 4 when '总分' then 5 enddrop table tb
      

  2.   

    pivot in sql server 2005
      

  3.   

    --行列互换/*--有表
    indust     200301     200302     200303     
    ---------- ---------- ---------- ---------- 
    a          111        222        333
    b          444        555        666
    c          777        888        999
    d          789        910        012
    --要求得到结果
    日期     a    b    c    d    
    ------ ---- ---- ---- ---- 
    200301 111  444  777  789
    200302 222  555  888  910
    200303 333  666  999  012
    --*/--创建测试表
    create table test(indust varchar(10)
    ,[200301] varchar(10)
    ,[200302] varchar(10)
    ,[200303] varchar(10))
    insert test select 'a','111','222','333'
    union all select 'b','444','555','666' 
    union all select 'c','777','888','999'
    union all select 'd','789','910','012'
    go--数据处理
    declare @f1 varchar(8000),@f2 varchar(8000),@f3 varchar(8000)
    select @f1='',@f2='',@f3=''
    select @f1=@f1+',['+indust+']='''+[200301]+''''
    ,@f2=@f2+','''+[200302]+''''
    ,@f3=@f3+','''+[200303]+''''
    from test
    exec('select 日期=''200301'''+@f1
    +' union all select ''200302'''+@f2
    +' union all select ''200303'''+@f3)
    go
    --删除测试表
    select * from test
    drop table test/*--测试结果
    日期     a    b    c    d    
    ------ ---- ---- ---- ---- 
    200301 111  444  777  789
    200302 222  555  888  910
    200303 333  666  999  012
    --*/
      

  4.   

    參照:
    http://blog.csdn.net/roy_88/archive/2008/07/26/2715856.aspx
      

  5.   

    --> --> 
     
    if not object_id('T') is null
    drop table T
    Go
    Create table T([项目] nvarchar(9),[2006.4.28] decimal(18,2),[2006.8.19] decimal(18,2),[2007.3.19] decimal(18,2),[2007.05.19] decimal(18,2))
    Insert T
    select N'活期存款',0.72,0.72,0.72,0.72 union all
    select N'整存整取(三个月)',1.71,1.8,1.98,2.07 union all
    select N'整存整取(半年)',2.07,2.25,2.43,2.61 union all
    select N'整存整取(一年)',2.25,2.52,2.79,3.06
    Go
      
     declare @s nvarchar(4000),@s2 nvarchar(4000),@s3 nvarchar(4000),@s4 nvarchar(4000)  
     select   
         @s=isnull(@s+',','declare ')+'@'+rtrim(Colid)+' nvarchar(4000)',  
         @s2=isnull(@s2+',','select ')+'@'+rtrim(Colid)+'='''+case when @s2 is not null then N'union all select' else ' select ' end+N'  [日期]='''+quotename(Name,'''')+'''''',  
         @s3=isnull(@s3,'')+'select @'+rtrim(Colid)+'=@'+rtrim(Colid)+N'+'',''+quotename([项目])+''=''+quotename('+quotename(Name)+','''''''')  from T ',  
         @s4=isnull(@s4+'+','')+'@'+rtrim(Colid)  
     from   
         syscolumns   
     where  
         id=object_id('T') and Name not in(N'项目')  
     --print @s+' '+@s2+' '+@s3+' exec('+@s4+')' 显示执行语句  
     exec(@s+' '+@s2+' '+@s3+' exec('+@s4+')')  日期         活期存款 整存整取(三个月) 整存整取(半年) 整存整取(一年)
    ---------- ---- --------- -------- --------
    2006.4.28  0.72 1.71      2.07     2.25
    2006.8.19  0.72 1.80      2.25     2.52
    2007.3.19  0.72 1.98      2.43     2.79
    2007.05.19 0.72 2.07      2.61     3.06(4 個資料列受到影響)
      

  6.   

    每天都有行列互换- -
    http://blog.csdn.net/roy_88/archive/2008/07/26/2715856.aspx
      

  7.   

    roy_88:
    还有十四行四列由于空间所限就没有列进来,但是你的行列处理好像每一个都不一样,我怎么加入啊?
     select   
         @s=isnull(@s+',','declare ')+'@'+rtrim(Colid)+' nvarchar(4000)',  
         @s2=isnull(@s2+',','select ')+'@'+rtrim(Colid)+'='''+case when @s2 is not null then N'union all select' else ' select ' end+N'  [日期]='''+quotename(Name,'''')+'''''',  
         @s3=isnull(@s3,'')+'select @'+rtrim(Colid)+'=@'+rtrim(Colid)+N'+'',''+quotename([项目])+''=''+quotename('+quotename(Name)+','''''''')  from T ',  
         @s4=isnull(@s4+'+','')+'@'+rtrim(Colid)  
     from   
      

  8.   

    --行列互转
    /******************************************************************************************************************************************************
    以学生成绩为例子,比较形象易懂整理人:中国风(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 行受影响)
    */
      

  9.   


    SQL2005時declare @s nvarchar(4000),@s2 nvarchar(4000),@s3 nvarchar(4000),@s4 nvarchar(4000)  --定義為nvarchar(max)2000時超過8000個字節需要用臨時表處理