服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Mysql - SQL中如何将行转成列详解

SQL中如何将行转成列详解

2022-12-01 16:42流楚丶格念 Mysql

行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧,下面这篇文章主要给大家介绍了关于SQL中如何将行转成列的相关资料,需要的朋友可以参考下

天天这需求就神奇!!!!

SQL中怎么将行转成列?

我们以MySQL数据库为例,来说明行转列的实现方式。

首先,假设我们有一张分数表(tb_score),表中的数据如下图:

SQL中如何将行转成列详解

然后,我们再来看一下转换之后需要得到的结果,如下图:

SQL中如何将行转成列详解

可以看出,这里行转列是将原来的subject字段的多行内容选出来,作为结果集中的不同列,并根据userid进行分组显示对应的score。通常,我们有两种方式来实现这种转换。

1. 使用 CASE…WHEN…THEN 语句实现行转列,参考如下代码:

?
1
2
3
4
5
6
7
SELECT userid,
SUM(CASE `subject` WHEN '语文' THEN score ELSE 0 END) as '语文',
SUM(CASE `subject` WHEN '数学' THEN score ELSE 0 END) as '数学',
SUM(CASE `subject` WHEN '英语' THEN score ELSE 0 END) as '英语',
SUM(CASE `subject` WHEN '政治' THEN score ELSE 0 END) as '政治'
FROM tb_score
GROUP BY userid

注意,SUM() 是为了能够使用GROUP BY根据userid进行分组,因为每一个userid对应的
subject="语文"的记录只有一条,所以SUM() 的值就等于对应那一条记录的score的值。假如userid ='001' and subject='语文' 的记录有两条,则此时SUM() 的值将会是这两条记录的和,同理,使用Max()的值将会是这两条记录里面值最大的一个。但是正常情况下,一个user对应一个subject只有一个分数,因此可以使用SUM()、MAX()、MIN()、AVG()等聚合函数都可以达到行转列的效果。

2. 使用 IF() 函数实现行转列,参考如下代码:

?
1
2
3
4
5
6
7
SELECT userid,
SUM(IF(`subject`='语文',score,0)) as '语文',
SUM(IF(`subject`='数学',score,0)) as '数学',
SUM(IF(`subject`='英语',score,0)) as '英语',
SUM(IF(`subject`='政治',score,0)) as '政治'
FROM tb_score
GROUP BY userid

注意, IF(subject='语文',score,0) 作为条件,即对所有subject='语文’的记录的score字段进行SUM()、MAX()、MIN()、AVG()操作,如果score没有值则默认为0。

补充:列转行:union

列转行是上述过程的逆过程,所以其思路也比较直观:

  • 行记录由一行变为多行,列字段由多列变为单列;
  • 一行变多行需要复制,列字段由多列变单列相当于是堆积的过程,其实也可以看做是复制;
  • 一行变多行,那么复制的最直观实现当然是使用union,即分别针对每门课程提取一张衍生表,最后将所有课程的衍生表union到一起即可,其中需要注意字段的对齐

按照这一思路,给出SQL实现如下:

?
1
2
3
SELECT uid,     
        sum(if(course='语文', score, NULL)) as `语文`,                      sum(if(course='数学', score, NULL)) as `数学`,                      sum(if(course='英语', score, NULL)) as `英语`,                      sum(if(course='物理', score, NULL)) as `物理`,     
        sum(if(course='化学', score, NULL)) as `化学`FROM scoreLongGROUP BY uid

查询结果当然是预期的长表。这里重点解释其中的三个细节:

在每个单门课的衍生表中,例如这句:SELECT uid, ‘语文’ as course, 语文 as score,用单引号包裹起来的课程名称是字符串常量,比如语文课的衍生表中的课程名都叫语文,然后将该列命名为course;第二个用反引号包裹起来的课程名实际上是从宽表中引用这一列的取值,然后将其命名为score。

这实际上对应的一个知识点是:在SQL中字符串的引用用单引号(其实双引号也可以),而列字段名称的引用则是用反引号.

上述用到了where条件过滤成绩为空值的记录,这实际是由于在原表中存在有空值的情况,如不加以过滤则在本例中最终查询记录有10条,其中两条记录的成绩字段为空

最后,本例中用union关键字实现了多表的纵向拼接,实际上用union all更为合理,二者的区别是union会完成记录去重;而union all则简单的拼接,在确定不存在重复或无需去重的情况下其效率更高。

总结

到此这篇关于SQL中如何将行转成列的文章就介绍到这了,更多相关SQL将行转成列内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_45525272/article/details/126477777

延伸 · 阅读

精彩推荐
  • Mysql设置MySQL中的数据类型来优化运行速度的实例

    设置MySQL中的数据类型来优化运行速度的实例

    这篇文章主要介绍了设置MySQL中索引的数据类型来优化运行速度的实例,主要是适当使用短字节的数据类型来处理短索引,需要的朋友可以参考下 ...

    吴炳锡2522020-05-07
  • MysqlmySQL 延迟 查询主表

    mySQL 延迟 查询主表

    在主外键表存在关系的时候如果加上"lazy=true"的话,则表明延迟,即只查询主表中的内容,而不查询外键表中的内容。 ...

    mysql教程网4732019-11-01
  • MysqlLinux/Mac MySQL忘记密码怎么办

    Linux/Mac MySQL忘记密码怎么办

    Linux/Mac MySQL忘记密码怎么办?这篇文章主要介绍了MySQL忘记密码的解决方法,命令行进行修改,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    MYSQL教程网4302020-07-27
  • MysqlMySQL日志的详细分析实例

    MySQL日志的详细分析实例

    MySQL日志记录了MySQL数据库日常操作和错误信息,下面这篇文章主要给大家介绍了关于MySQL日志的详细分析,文中通过示例代码介绍的非常详细,需要的朋友可以...

    骏马金龙3862022-10-20
  • MysqlMySQL窗口函数优秀实践,你学会了吗?

    MySQL窗口函数优秀实践,你学会了吗?

    Mysql 8.0新增的窗口函数极大简化了sql实现语句,实现了更加复杂的数据逻辑,可以满足更多的开发场景,从而相应减少了代码开发成本。...

    Java技术指北5712022-11-03
  • Mysql详解MySQL中的存储过程和函数

    详解MySQL中的存储过程和函数

    这篇文章主要为大家详细介绍了MySQL数据库中的存储过程和函数的相关操作,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下...

    我的天才女友11782022-08-11
  • MysqlMySQL启用SSD存储的实例详解

    MySQL启用SSD存储的实例详解

    这篇文章主要介绍了MySQL启用SSD存储的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下...

    资深架构师5442020-08-18
  • MysqlMySQL读写分离,写完读不到问题如何解决

    MySQL读写分离,写完读不到问题如何解决

    今天我们来详细了解一下主从同步延迟时读写分离发生写后读不到的问题,依次讲解问题出现的原因,解决策略以及 Sharding-jdbc、MyCat 和 MaxScale 等开源数据...

    程序员历小冰6412021-03-08