5分钟搞懂MySQL - 行转列

这篇具有很好参考价值的文章主要介绍了5分钟搞懂MySQL - 行转列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

小伙伴想精准查找自己想看的MySQL文章?喏 → MySQL专栏目录 | 点击这里

  MySQL行转列,对经常处理数据的同学们来说,一定是不陌生的,甚至是印象深刻,因为它大概率困扰过你,让你为之一愣~ 但当你看到本文后,这个问题就不在是问题,及时收藏,以后谁再问你这个问题,直接甩他脸上,粘贴即用。

  这里告诉大家一个小秘密,其实我和《小欢喜》里面的几位是同学还是好朋友~~今天我就拿我们哥儿几个高考成绩表来当测试表。嗯,兄弟们不信?我还有我们在学校里的合影呢,高三那年还没有PS,所以照片肯定是真的!😉😉

5分钟搞懂MySQL - 行转列

废话不多说,首先,我们看一下咱们的测试表数据预期查询的结果

mysql> SELECT * FROM t_gaokao_score;
+----+--------------+--------------+-------+
| id | student_name | subject      | score |
+----+--------------+--------------+-------+
|  1 | 林磊儿       | 语文         |   148 |
|  2 | 林磊儿       | 数学         |   150 |
|  3 | 林磊儿       | 英语         |   147 |
|  4 | 乔英子       | 语文         |   121 |
|  5 | 乔英子       | 数学         |   106 |
|  6 | 乔英子       | 英语         |   146 |
|  7 | 方一凡       | 语文         |    70 |
|  8 | 方一凡       | 数学         |    90 |
|  9 | 方一凡       | 英语         |    59 |
| 10 | 方一凡       | 特长加分     |   200 |
| 11 | 陈哈哈       | 语文         |   109 |
| 12 | 陈哈哈       | 数学         |    92 |
| 13 | 陈哈哈       | 英语         |    80 |
+----+--------------+--------------+-------+
13 rows in set (0.00 sec)

看看我们行转列转完后的结果:

+--------------+--------+--------+--------+--------------+
| student_name | 语文   | 数学   | 英语   | 特长加分     |
+--------------+--------+--------+--------+--------------+
| 林磊儿       |    148 |    150 |    147 |            0 |
| 乔英子       |    121 |    106 |    146 |            0 |
| 方一凡       |     70 |     90 |     59 |          200 |
| 陈哈哈       |    109 |     92 |     80 |            0 |
+--------------+--------+--------+--------+--------------+
4 rows in set (0.00 sec)

  好,下面我们一起来看看SQL是如何编写的,对了,创建表结构和导入测试数据的SQL放到文章末尾了,自取~



一、行转列SQL写法

  • 方法一、使用case..when..then进行 行转列
SELECT student_name,
	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 t_gaokao_score 
GROUP BY student_name;

  这里如果不使用SUM()会报sql_mode=only_full_group_by相关错误,需要聚合函数和group by连用使用distinct才可以解决。

  其实,加了SUM()是为了能够使用GROUP BY根据student_name进行分组,每一个student_name对应的subject="语文"的记录毕竟只有一条,所以SUM() 的值就等于对应那一条记录的score的值。当然,也可以换成MAX()

5分钟搞懂MySQL - 行转列

  • 方法二、使用IF()进行 行转列:
SELECT student_name,
	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 t_gaokao_score 
GROUP BY student_name;

  该方法将IF(subject='语文',score,0)作为条件,通过student_name进行分组,对分组后所有subject='语文’的记录的score字段进行SUM()操作,如果score没有值则默认为0。

  这种方式和case..when..then方法原理相同,相比更加简洁明了,建议使用。

二、如果领导@你,让你在结果集中加上总数列呢?

友情提示我们工作中处理行转列数据时,尽量都把总数、平均数等加上,方便领导查阅,省得他循环BB你。

话说,你还记得上学时的成绩表是啥样的么?你一般从上往下看还是从下往上看呢?文末投票,快来给大家乐呵乐呵!

写法:利用SUM(IF()) 生成列,WITH ROLLUP 生成汇总列和行,并利用 IFNULL将汇总行标题显示为总数

SELECT IFNULL(student_name,'总数') AS student_name,
	SUM(IF(`subject`='语文',score,0)) AS '语文',
	SUM(IF(`subject`='数学',score,0)) AS '数学',
	SUM(IF(`subject`='英语',score,0)) AS '英语',
	SUM(IF(`subject`='特长加分',score,0)) AS '特长加分',
	SUM(score) AS '总数' 
FROM t_gaokao_score
GROUP BY student_name WITH ROLLUP;

查询结果:

+--------------+--------+--------+--------+--------------+--------+
| student_name | 语文   | 数学   | 英语   | 特长加分     | 总数   |
+--------------+--------+--------+--------+--------------+--------+
| 乔英子       |    121 |    106 |    146 |            0 |    373 |
| 方一凡       |     70 |     90 |     59 |          200 |    419 |
| 林磊儿       |    148 |    150 |    147 |            0 |    445 |
| 陈哈哈       |    113 |    116 |     80 |            0 |    309 |
| 总数         |    452 |    462 |    432 |          200 |   1546 |
+--------------+--------+--------+--------+--------------+--------+
5 rows in set, 1 warning (0.00 sec)

三、领导又双叒叕@你改需求

  让你把分值转化为具体内容显示(优秀、良好、普通、差),430分以上重点大学,400分以上一本,350分及以上二本,350以下搬砖,该怎么写呢?

  真恶心,不说了,先淦饭🐶🐶~~(独门绝技:饭遁

  这里我们就需要case when嵌套一下了,看着高大上,其实就是普通的嵌套而已。在第一层查出分组后的各科分数,在第二层替换成等级即可。

SELECT student_name,
MAX(  
        CASE subject  
        WHEN '语文' THEN  
            (  
                CASE  
                WHEN score - (select avg(score) from t_gaokao_score where subject='语文') > 20 THEN  
                    '优秀'  
                WHEN score - (select avg(score) from t_gaokao_score where subject='语文') > 10 THEN  
                    '良好'  
                WHEN score - (select avg(score) from t_gaokao_score where subject='语文') >= 0 THEN  
                    '普通'  
                ELSE  
                    '差'  
                END  
            )  
        END  
    ) as '语文', 
MAX(  
        CASE subject  
        WHEN '数学' THEN  
            (  
                CASE  
                WHEN score - (select avg(score) from t_gaokao_score where subject='数学') > 20 THEN  
                    '优秀'  
                WHEN score - (select avg(score) from t_gaokao_score where subject='数学') > 10 THEN  
                    '良好'  
                WHEN score - (select avg(score) from t_gaokao_score where subject='数学') >= 0 THEN  
                    '普通'  
                ELSE  
                    '差'  
                END  
            )  
        END  
    ) as '数学',
MAX(  
        CASE subject  
        WHEN '英语' THEN  
            (  
                CASE  
                WHEN score - (select avg(score) from t_gaokao_score where subject='英语') > 20 THEN  
                    '优秀'  
                WHEN score - (select avg(score) from t_gaokao_score where subject='英语') > 10 THEN  
                    '良好'  
                WHEN score - (select avg(score) from t_gaokao_score where subject='英语') >= 0 THEN  
                    '普通'  
                ELSE  
                    '差'  
                END  
            )  
        END  
    ) as '英语',
SUM(score) as '总分',
(CASE WHEN SUM(score) > 430 THEN '重点大学'  
	  WHEN SUM(score) > 400 THEN '一本'  
	  WHEN SUM(score) > 350 THEN '二本'  
	  ELSE '工地搬砖' 
	  END ) as '结果'
FROM t_gaokao_score 
GROUP BY student_name 
ORDER BY SUM(score) desc;

我们来看一下输出结果:

+--------------+--------+--------+--------+--------+--------------+
| student_name | 语文   | 数学   | 英语   | 总分   | 结果         |
+--------------+--------+--------+--------+--------+--------------+
| 林磊儿       | 优秀   | 优秀   | 优秀   |    445 | 重点大学     |
| 方一凡       ||||    419 | 一本         |
| 乔英子       | 普通   || 优秀   |    373 | 二本         |
| 陈哈哈       | 普通   | 普通   ||    309 | 工地搬砖     |
+--------------+--------+--------+--------+--------+--------------+
4 rows in set (0.00 sec)

过来人的经验来看,老实孩子最吃亏,早知道他娘的走艺体了~

四、结束语

  好了,SQL方面就是以上这些内容了,有疑问可以写在评论区,哈哥会在摸鱼的时候回复你~~`

  帮忙三连一下哦,比心ღ( ´・ᴗ・` )

5分钟搞懂MySQL - 行转列

附录:创建表结构&测试数据SQL

表结构:

DROP TABLE IF EXISTS `t_gaokao_score`;
CREATE TABLE `t_gaokao_score`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `student_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '学生姓名',
  `subject` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '科目',
  `score` double NULL DEFAULT NULL COMMENT '成绩',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

导入测试数据文章来源地址https://www.toymoban.com/news/detail-404206.html

INSERT INTO `t_gaokao_score` VALUES 
(1, '林磊儿', '语文', 148),
(2, '林磊儿', '数学', 150),
(3, '林磊儿', '英语', 147),
(4, '乔英子', '语文', 121),
(5, '乔英子', '数学', 106),
(6, '乔英子', '英语', 146),
(7, '方一凡', '语文', 70),
(8, '方一凡', '数学', 90),
(9, '方一凡', '英语', 59),
(10, '方一凡', '特长加分', 200),
(11, '陈哈哈', '语文', 109),
(12, '陈哈哈', '数学', 92),
(13, '陈哈哈', '英语', 80);

到了这里,关于5分钟搞懂MySQL - 行转列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 搞定mysql的 行转列(7种方法) 和 列转行

    一、行转列 1、使用case…when…then  2、使用SUM(IF()) 生成列 3、使用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行 4、使用SUM(IF()) 生成列,直接生成汇总结果,不再利用子查询 5、使用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total 6、动态查询列值不确定的情况

    2024年03月12日
    浏览(53)
  • Mysql一维表转二维表,动态的行转列

    背景 想利用Grafana做数据展示,将一维的长表优化成二维数据表格展示。 将一维表转换为二维表,也就是将行转换为列,可以使用MySQL的PIVOT语句来完成。 PIVOT是一种在关系型数据库中将行转换为列的技术。在MySQL中,可以使用PIVOT语句将普通的查询结果转换为一个带有动态列

    2024年02月15日
    浏览(42)
  • MySQL中的面试题——行转列(列转行)手把手详解思想

    目录 1、什么是行转列,列转行 ? 1.1、概念: 1.2、行转列和列转行的思想 1.2.1、行转列的思想? 1.2.2、列转行的思想? 3、实操讲解 3.1、实现行转列  3.2、总结:行转列实现的两种方法    3.3、实现列转行  3.4、总结 :列转行 4、动手练习         在MySQL中,行转列(

    2024年02月03日
    浏览(60)
  • mysql~GROUP_CONCAT实现关系表的行转列

    GROUP_CONCAT 是 MySQL 中用于将查询结果集中的多行数据合并为单个字符串的聚合函数。它将每行数据的指定字段值连接起来,并以指定的分隔符分隔,最终返回一个包含所有值的字符串。 以下是 GROUP_CONCAT 函数的一般语法: column_name:要连接的字段名。 SEPARATOR:可选参数,用于

    2024年04月12日
    浏览(36)
  • greenplum行转列

    项目中需要将150w的数据转为1500列的大宽表数据。 最开始尝试了网上提供的两种方法: 实际业务中10行*1500列数据查询并插入需要25秒左右(测试服务器性能比较差) case when的问题是每个case when的语句都会把分组后的数据判断一下,时间复杂度为O²(O为行转列后的列数),非

    2024年02月03日
    浏览(40)
  • SqlServer行转列方法

    数据库建表 1 使用聚合函数巧妙解决,可以用max、sum等 2 使用pivot函数 3.行转列,多列,参考

    2024年02月15日
    浏览(68)
  • sql 行转列

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 实现行转列的两种方式,case when 与piovt 函数的使用例子与比对 示例:如需要将左边的表格转换成右边的表格 首先,根据资产属性先将数据分成四列 代码如下:` 结果如下: I 这样看起来比较乱,需要根

    2024年02月09日
    浏览(40)
  • PostgreSQL如何行转列

    PostgreSQL如何行转列 方法一: group by + sum + case when 方法二: 用postgresql的crosstab交叉函数 方法三: group by + string_agg + split_part(分组,行转列,字符切割) group by + string_agg

    2024年02月11日
    浏览(53)
  • Hive数据仓库行转列

    查了很多资料发现网上很多文章都是转发和抄袭,有些问题。这里分享一个自己项目中使用的行转列例子,供大家参考。代码如下: 如果是在SparkSQL或Presto平台,或者阿里云的MaxCompute平台,还可使用如下方式:

    2024年02月21日
    浏览(58)
  • Oracle——行转列与列转行

    把某一个字段的值作为唯一值,然后另外一个字段的 行值转换成它的列值 。 转换过程大致如下所示: 通常情况下,采取 group by 唯一字段 进行分组,然后依据不同的列进行判断输出就能转换。 建表语句和增加测试数据sql如下所示: 执行完毕后,数据库中当前的数据结构如

    2024年02月15日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包