zoukankan      html  css  js  c++  java
  • MySQL行列转换

    实际应用中,会遇到需要把表的某些行转换成列,或者把列转换成行的情况。比如一张表在数据库中是这样的:

     图1

    但是,需要的结果可能是这样:

     图2

    这个时候就得行列转换了。

    1.行转列的几种方法

    1.1 case ...  when  ... then ... else ... end

    select uname,uid, -- 正常查询的字段
    sum(
    case
    when course ='英语' then score -- 需要转换的字段
    else 0
    end) '英语',
    sum(
    case 
    when course= '物理' then score
    else 0
    end) '物理',
    sum(
    case  
    when course='化学' then score
    else 0
    end) '化学' 
    from course
    group by uid

    另一种写法:

    case course 
    when '化学' then score
    else 0
    end

    另外若省略‘else 0‘,则没有该课程的同学的分数会填充为null; sum替换成max结果一样。

    1.2  if (`字段名1`=‘字段值’,,)

    select uname,uid,
    sum(if(`course`='英语',score,0)) '英语',
    sum(if(`course`='物理',score,0)) '物理',
    sum(if(`course`='化学',score,0)) '化学'
    from course
    group by uname
    

      

    貌似比第一种方法简洁一些,所以下面的扩展是基于这种方法的~

    以上两种转换方法结果相同,如图2。另外实际应用中还可能需要有总计的结果,如图3.

     图3

    total这一列简单,直接在之前的查询基础上加一个sum(score) 'total'即可;Total这一行则可以看成之前的查询不加group by而聚合成一行。因此可以看做是两个表组合到一起如图4和图5:

     图4

     图5

    1.3  if (`字段名1`=‘字段值’,,) + union

    把两个查询结果拼接到一起就是图3的样子了,代码如下:

    select uid,uname,
    sum(if(`course`='英语',score,0)) '英语',
    sum(if(`course`='物理',score,0)) '物理',
    sum(if(`course`='化学',score,0)) '化学',
    sum(score) 'total'
    from course
    group by uname
    union 
    select 'Total',null,
    sum(if(`course`='英语',score,0)) '英语',
    sum(if(`course`='物理',score,0)) '物理',
    sum(if(`course`='化学',score,0)) '化学',
    sum(score) 'total'
    from course
    

      

    1.4  if (`字段名1`=‘字段值’,,) + IFNULL()+with rollup

    这种方法效果同1.3,

    select ifnull(uid,'Total') uid, uname,
    sum(if(`course`='英语',score,0)) '英语',
    sum(if(`course`='物理',score,0)) '物理',
    sum(if(`course`='化学',score,0)) '化学',
    sum(score) 'total'
    from course
    group by uid
    with ROLLUP
    

      

    比1.3简洁一些,效率应该也高一点。with rollup和group by配套使用,会在已有的查询结果上再多出一行,对结果再聚合成一行,即图5的那一行,若不是数字类型,则返回最下面一行的数据,最后一行分组的字段会显示null,因此在配合ifnull()就可以了。

    有瑕疵,想把它变成 null,有待完善。

    2.列转行

    列转行刚好和行转列情况相反,即:

    数据库中存储的是这样

     图2

    而我们需要这样的结果

     图1

    没有在创建新表,暂且把这个视图当成新表吧

    create view rtc as
    select ifnull(uid,'Total') uid,uname,
    sum(if(`course`='英语',score,0)) '英语',
    sum(if(`course`='物理',score,0)) '物理',
    sum(if(`course`='化学',score,0)) '化学',
    sum(score) 'total'
    from course
    group by uid
    with ROLLUP
    -- 下面是列转行代码
    select uid,uname,'英语' course,英语 score from rtc where uid <>'Total' and 英语>0
    union all select uid,uname,'物理' ,物理 from rtc where uid <>'Total' and 物理>0
    union all select uid,uname,'化学' ,化学 from rtc where uid <>'Total' and 化学>0
    

      

  • 相关阅读:
    mybatis批量插入、批量更新和批量删除
    MySQL本地密码过期处理及永不过期设置
    Intellij IDEA安装与使用,完整详细。
    深入浅出mybatis之useGeneratedKeys参数用法
    springmvc_learn
    Mac下,MySQL数据库中文乱码的解决方法
    springmvc整合mybatis实现商品列表查询
    sql server 数据库导出表里所有数据成insert 语句
    推荐几个bootstrap 后端UI框架
    50个极好的bootstrap框架
  • 原文地址:https://www.cnblogs.com/chenyablog/p/15322573.html
Copyright © 2011-2022 走看看