玩转-数据库行列转换

系统 1670 0

虽然开发过程中没用过行列转换,但是听说面试时常常会遇到这个问题,以前在网上也看到过大神的例子,今天自己仔细的玩了下,希望和大家分享一下了。

注意:列转行的方法可能是我独创的了,呵呵,因为在网上找不到哦,全部是我自己写的,用到了系统的SysColumns

(一)行转列的方法

先说说行转列的方法,这个就比较好想了,利用拼sql和case when解决即可

实现目的 玩转-数据库行列转换

1:建立测试用的数据库

    
      CREATE TABLE RowTest(

    [Name] [nvarchar](
    
    
      10
    
    ) NULL,--
    
      名稱

    [Course] [nvarchar](
    
    
      10
    
    ) NULL,--
    
      課程名稱

    [Record] [
    
    
      int
    
    ] NULL--
    
      課程的分數

)
      
2:加入测试用的数据库(先加入整齐的数据)
        insert into RowTest values (
        
          '
        
        
          张三
        
        
          '
        
        ,
        
          '
        
        
          语文
        
        
          '
        
        ,
        
          '
        
        
          91
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          张三
        
        
          '
        
        ,
        
          '
        
        
          数学
        
        
          '
        
        ,
        
          '
        
        
          92
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          张三
        
        
          '
        
        ,
        
          '
        
        
          英语
        
        
          '
        
        ,
        
          '
        
        
          93
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          张三
        
        
          '
        
        ,
        
          '
        
        
          生物
        
        
          '
        
        ,
        
          '
        
        
          94
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          张三
        
        
          '
        
        ,
        
          '
        
        
          物理
        
        
          '
        
        ,
        
          '
        
        
          95
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          张三
        
        
          '
        
        ,
        
          '
        
        
          化学
        
        
          '
        
        ,
        
          '
        
        
          96
        
        
          '
        
        
          )



insert into RowTest values (
        
        
          '
        
        
          李四
        
        
          '
        
        ,
        
          '
        
        
          语文
        
        
          '
        
        ,
        
          '
        
        
          81
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          李四
        
        
          '
        
        ,
        
          '
        
        
          数学
        
        
          '
        
        ,
        
          '
        
        
          82
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          李四
        
        
          '
        
        ,
        
          '
        
        
          英语
        
        
          '
        
        ,
        
          '
        
        
          83
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          李四
        
        
          '
        
        ,
        
          '
        
        
          生物
        
        
          '
        
        ,
        
          '
        
        
          84
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          李四
        
        
          '
        
        ,
        
          '
        
        
          物理
        
        
          '
        
        ,
        
          '
        
        
          85
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          李四
        
        
          '
        
        ,
        
          '
        
        
          化学
        
        
          '
        
        ,
        
          '
        
        
          86
        
        
          '
        
        
          )



insert into RowTest values (
        
        
          '
        
        
          小生
        
        
          '
        
        ,
        
          '
        
        
          语文
        
        
          '
        
        ,
        
          '
        
        
          71
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          小生
        
        
          '
        
        ,
        
          '
        
        
          数学
        
        
          '
        
        ,
        
          '
        
        
          72
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          小生
        
        
          '
        
        ,
        
          '
        
        
          英语
        
        
          '
        
        ,
        
          '
        
        
          73
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          小生
        
        
          '
        
        ,
        
          '
        
        
          生物
        
        
          '
        
        ,
        
          '
        
        
          74
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          小生
        
        
          '
        
        ,
        
          '
        
        
          物理
        
        
          '
        
        ,
        
          '
        
        
          75
        
        
          '
        
        
          )

insert into RowTest values (
        
        
          '
        
        
          小生
        
        
          '
        
        ,
        
          '
        
        
          化学
        
        
          '
        
        ,
        
          '
        
        
          76
        
        
          '
        
        )
      
View Code
  

3:设计想法

  行转列的原理就是把行的类别找出来当做查询的字段,利用case when 把当前的分数加到当前的字段上去,最后用group by 把数据整合在一起

4:通用方法

        
          declare
        
        
          @sql
        
        
          nvarchar
        
        (
        
          max
        
        
          )


        
        
          set
        
        
          @sql
        
        
          =
        
        
          '
        
        
          select Name
        
        
          '
        
        
          select
        
        
          @sql
        
        
          =
        
        
          @sql
        
        
          +
        
        
          '
        
        
          ,
        
        
          '
        
        
          +
        
        
          '
        
        
          isnull(max( case when Course=
        
        
          '''
        
        
          +
        
        TCourse.Course
        
          +
        
        
          '''
        
        
           then Record end ),0)
        
        
          '
        
        
          +
        
        
          TCourse.Course

 
        
        
          from
        
         (
        
          select
        
        
          distinct
        
         Course 
        
          from
        
        
           RowTest)TCourse 




        
        
          set
        
        
          @sql
        
        
          =
        
        
          @sql
        
        
          +
        
        
          '
        
        
           from RowTest group by Name order by Name
        
        
          '
        
        
          print
        
        
          @sql
        
        
          exec
        
        (
        
          @sql
        
        )
      
View Code

说明: 把所有的课程名称取出来作为列(查询表TCourse)

        用case when 的方法把sql 拼出来

5:课外试验

(1)加入数据

    insert into dbo.RowTest values (
    
      '
    
    
      小生
    
    
      '
    
    ,
    
      '
    
    
      生物
    
    
      '
    
    ,
    
      '
    
    
      110
    
    
      '
    
    )
    
去除max 方法会报错,因为一条可能对应多行数据

(2)加入数据

    insert into dbo.RowTest values (
    
      '
    
    
      小生
    
    
      '
    
    ,
    
      '
    
    
      計算機
    
    
      '
    
    ,
    
      '
    
    
      110
    
    
      '
    
    )
  

数据会多出一列,但是其他人无此课程就会为0

至此,数据行转列ok 

(二)列转行的新方法开始了

实现目的

玩转-数据库行列转换

 

1:实现原理

在网上看了别人的做法,基本都是用union all 来一个个转换的,我觉得不太好用。

首先我想到了要把所有的列名取出来,就在网上查了下获取表的所有列名

 然后我可以把主表和列名形成的表串起来,这样就可以形成需要的列数,然后根据判断取值就完成了了,呵呵

2:建立表格

        
          create
        
        
          table
        
        
           CoulumTest

(

 Name 
        
        
          nvarchar
        
        (
        
          10
        
        
          ),

 语文  
        
        
          int
        
        
          ,

 数学 
        
        
          int
        
        
          ,

 英语 
        
        
          int
        
        
          

 

)
        
      
View Code

3:加入数据

    insert into CoulumTest values(N
    
      '
    
    
      张三
    
    
      '
    
    ,
    
      90
    
    ,
    
      91
    
    ,
    
      92
    
    
      )

insert into CoulumTest values(N
    
    
      '
    
    
      李四
    
    
      '
    
    ,
    
      80
    
    ,
    
      81
    
    ,
    
      82
    
    )
    
4:经典的地方来了
        
          select
        
        
           CT.Name,Col.name 课程,

(
        
        
          case
        
        
          when
        
         Col.name
        
          =
        
        N
        
          '
        
        
          语文
        
        
          '
        
        
          then
        
         CT.语文  
        
          when
        
         Col.name
        
          =
        
        N
        
          '
        
        
          数学
        
        
          '
        
        
          then
        
        
           CT.数学

 
        
        
          when
        
         Col.name
        
          =
        
        N
        
          '
        
        
          英语
        
        
          '
        
        
          then
        
         CT.英语 
        
          end
        
         ) 
        
          as
        
         分数 
        
          from
        
        
           CoulumTest CT


        
        
          left
        
        
          join
        
         (
        
          select
        
         name 
        
          from
        
         SysColumns  
        
          Where
        
         id
        
          =
        
        
          Object_Id
        
        (
        
          '
        
        
          CoulumTest
        
        
          '
        
        )) Col 
        
          on
        
         Col.name
        
          <>
        
        
          '
        
        
          Name
        
        
          '
        
      
View Code

你没看错,一句话搞定,但是有个问题迷惑了我,我觉得还不够简化,如果可以把case when 都不用了就更好了,请大神们指点小弟一下了。怎么根据

Col的name 直接取得分数

    
       
    
  

玩转-数据库行列转换


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论