sql server 纵横表的转换

系统 2616 0

在平常的工作中或者面试中,我们可能有遇到过数据库的纵横表的转换问题。今天我们就来讨论下。

1.创建表

  首先我们来创建一张表。

sql语句:

      
         1
      
      
        --
      
      
        1. 创建数据表
      
      
         2
      
      
        if
      
      
        OBJECT_ID
      
      (
      
        '
      
      
        Score
      
      
        '
      
      ) 
      
        is
      
      
        not
      
      
        null
      
      
        drop
      
      
        table
      
      
         Score


      
      
         3
      
      
         4
      
      
        create
      
      
        table
      
      
         Score


      
      
         5
      
      
        (


      
      
         6
      
           姓名 
      
        nvarchar
      
      (
      
        128
      
      
        ),


      
      
         7
      
           课程 
      
        nvarchar
      
      (
      
        128
      
      
        ),


      
      
         8
      
           分数 
      
        int
      
      
         9
      
      
        )


      
      
        10
      
      
        11
      
      
        insert
      
      
        into
      
       Score 
      
        values
      
      (
      
        '
      
      
        张三
      
      
        '
      
      ,
      
        '
      
      
        语文
      
      
        '
      
      ,
      
        98
      
      
        )


      
      
        12
      
      
        insert
      
      
        into
      
       Score 
      
        values
      
      (
      
        '
      
      
        张三
      
      
        '
      
      ,
      
        '
      
      
        数学
      
      
        '
      
      ,
      
        89
      
      
        )


      
      
        13
      
      
        insert
      
      
        into
      
       Score 
      
        values
      
      (
      
        '
      
      
        张三
      
      
        '
      
      ,
      
        '
      
      
        物理
      
      
        '
      
      ,
      
        78
      
      
        )


      
      
        14
      
      
        insert
      
      
        into
      
       Score 
      
        values
      
      (
      
        '
      
      
        李四
      
      
        '
      
      ,
      
        '
      
      
        语文
      
      
        '
      
      ,
      
        79
      
      
        )


      
      
        15
      
      
        insert
      
      
        into
      
       Score 
      
        values
      
      (
      
        '
      
      
        李四
      
      
        '
      
      ,
      
        '
      
      
        数学
      
      
        '
      
      ,
      
        88
      
      
        )


      
      
        16
      
      
        insert
      
      
        into
      
       Score 
      
        values
      
      (
      
        '
      
      
        李四
      
      
        '
      
      ,
      
        '
      
      
        物理
      
      
        '
      
      ,
      
        100
      
      
        )


      
      
        17
      
      
        18
      
      
        select
      
      
        *
      
      
        from
      
       Score
    

执行结果:

sql server 纵横表的转换

2. 传统的纵横表转换

2.1 纵表转横表

先看看我们要转成的横表张什么样子:

既然这个表只有两列,那么可以根据姓名进行分组。先把姓名拼凑出来,后面的分数我们再想办法。

sql:

      
        select
      
       t.姓名 
      
        2
      
      
        from
      
       Score 
      
        as
      
       t 
      
        3
      
      
        group
      
      
        by
      
       t.姓名 
    

结果:

 

分析:

  1. 我们先拿到语文这个科目的分数。既然我们用到了group by 语句,这里肯定要用聚合函数来求分数。
  2. 而且我们只需要语文这一科的成绩,分组出来的 一共有 3列 ,分别是 语文、数学、物理  。  那么就需要判断科目来取分数。

  这里符合我们需求的 case 语句就登场了。他和c#中switch-case 作用一样。

sql case 语句语法: 

      
        case
      
      
         字段

    
      
      
        when
      
       值1 
      
        then
      
      
         结果

    
      
      
        when
      
       值2 
      
        then
      
      
         结果2

    ...

    
      
      
        else
      
      
         默认结果


      
      
        end
      
    

 

求语文的分数就简单了:

      
        select
      
      
         t.姓名,


      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        语文
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         语文


      
      
        from
      
       Score 
      
        as
      
      
         t


      
      
        group
      
      
        by
      
       t.姓名
    

结果:

 

既然语文的分数取到了,其他科目改变下条件就可以了。

完整的sql:

      
        select
      
      
         t.姓名,


      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        语文
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         语文,


      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        数学
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         数学,


      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        物理
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         物理


      
      
        from
      
       Score 
      
        as
      
      
         t


      
      
        group
      
      
        by
      
       t.姓名
    

OK,到这儿,我们传统方式的纵表转横表就大功告成了。

 

2.2 横表转纵表

那么我们可以把转换过来的横表再转换回去吗?  

我们先把刚刚转好的表,插入一个新表ScoreHb 中。

      
        1
      
      
        --
      
      
         转换的表插入新表
      
      
        2
      
      
        select
      
      
         t.姓名,


      
      
        3
      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        语文
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         语文,


      
      
        4
      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        数学
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         数学,


      
      
        5
      
      
        SUM
      
      (
      
        case
      
       t.课程 
      
        when
      
      
        '
      
      
        物理
      
      
        '
      
      
        then
      
       t.分数 
      
        else
      
      
        0
      
      
        end
      
      ) 
      
        as
      
      
         物理


      
      
        6
      
      
        into
      
      
         ScoreHb


      
      
        7
      
      
        from
      
       Score 
      
        as
      
      
         t


      
      
        8
      
      
        group
      
      
        by
      
       t.姓名
    

这时ScoreHb 就是我们刚转换好的横表,我们再想办法把他转回来。

怎么转呢? 一步步来。我们也先把张三和李四的语文成绩查出来。

sql:

      
        1
      
      
        --
      
      
        张三李四语文的分数
      
      
        2
      
      
        select
      
      
         t.姓名,


      
      
        3
      
      
        '
      
      
        语文
      
      
        '
      
      
        as
      
      
         课程,


      
      
        4
      
       t.语文 
      
        as
      
      
         分数


      
      
        5
      
      
        from
      
       ScoreHb 
      
        as
      
       t
    

结果:

还有两科的数据怎么办呢? 很简单,我们一个个都查出来,然后用 union all 把他们组合为一张表就可以了。

sql:

      
         1
      
      
        --
      
      
         union all链接3个科目
      
      
         2
      
      
        select
      
      
         t.姓名,


      
      
         3
      
      
        '
      
      
        语文
      
      
        '
      
      
        as
      
      
         课程,


      
      
         4
      
       t.语文 
      
        as
      
      
         分数


      
      
         5
      
      
        from
      
       ScoreHb 
      
        as
      
      
         t


      
      
         6
      
      
        union
      
      
        all
      
      
         7
      
      
        select
      
      
         t.姓名,


      
      
         8
      
      
        '
      
      
        数学
      
      
        '
      
      
        as
      
      
         课程,


      
      
         9
      
       t.数学 
      
        as
      
      
         分数


      
      
        10
      
      
        from
      
       ScoreHb 
      
        as
      
      
         t


      
      
        11
      
      
        union
      
      
        all
      
      
        12
      
      
        select
      
      
         t.姓名,


      
      
        13
      
      
        '
      
      
        物理
      
      
        '
      
      
        as
      
      
         课程,


      
      
        14
      
       t.物理 
      
        as
      
      
         分数


      
      
        15
      
      
        from
      
       ScoreHb 
      
        as
      
      
         t


      
      
        16
      
      
        order
      
      
        by
      
       t.姓名 desc
    

 

结果:

sql server 纵横表的转换

 

这样,我们就把表又变回去了。

但是大家有没有觉得很麻烦呢?别急,我们有更简单的办法。下面为大家介绍pivot关系运算符。

3. 用pivot和unpivot运算符进行转换

  pivot是sql server 2005 提供的运算符,所以只要数据库在05版本以上的都可以使用。主要用于行和列的转换。

3.1 pivot纵表转横表

sql:

      
        1
      
      
        select
      
      
        2
      
      
            t2.姓名,


      
      
        3
      
      
            t2.数学,


      
      
        4
      
      
            t2.物理,


      
      
        5
      
      
            t2.语文


      
      
        6
      
      
        from
      
       Score 
      
        as
      
      
         t1


      
      
        7
      
       pivot (
      
        sum
      
      (分数) 
      
        for
      
       课程 
      
        in
      
      (数学,语文,物理)) 
      
        as
      
       t2
    

结果:

 

是不是代码简洁多了。

pivot将原来表中 课程字段中的 数据行 数学,语文,物理 转换为列,并用sum取对应列的值。

我们只需要记住它的用法就可以了。

 

3.2 unpivot 横表转纵表

既然有privot可以纵表转横表。那么有没有运算符帮我们转回来呢?

答案是肯定的,他就是unpivot

 

sql:

      
        1
      
      
        select
      
      
        2
      
      
        *
      
      
        3
      
      
        from
      
      
        4
      
      
        ScoreHb


      
      
        5
      
       unpivot (分数 
      
        for
      
       课程 
      
        in
      
       (语文,数学,物理)) 
      
        as
      
       t4
    

结果:

sql server 纵横表的转换

 unpivot 将 语文,数学,物理 列转为行,分数为新的一列存放对应的值。

 是不是比我们之前一个个表查询拼接,方便了很多。

 

sql server 纵横表的转换


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

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

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

【本文对您有帮助就好】

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

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