5分钟搞懂MySQL - 行转列

举报
lxw1844912514 发表于 2022/06/21 22:53:07 2022/06/21
【摘要】 首先,创建表结构和导入测试数据的SQL #创建表结构DROP TABLE IF EXISTS `t_gaokao_score`;CREATE TABLE `t_gaokao_score`  (  `id` int(0)&...

首先,创建表结构和导入测试数据的SQL


   
  1. #创建表结构
  2. DROP TABLE IF EXISTS `t_gaokao_score`;
  3. CREATE TABLE `t_gaokao_score`  (
  4.   `id` int(0) NOT NULL AUTO_INCREMENT,
  5.   `student_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '学生姓名',
  6.   `subject` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '科目',
  7.   `score` double NULL DEFAULT NULL COMMENT '成绩',
  8.   PRIMARY KEY (`id`) USING BTREE
  9. ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
#导入测试数据
  

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

然后,我们看一下咱们的测试表数据和预期查询的结果。


   
  1. #来源公众号【码农编程进阶笔记】
  2. mysql> SELECT * FROM t_gaokao_score;
  3. +----+--------------+--------------+-------+
  4. | id | student_name | subject      | score |
  5. +----+--------------+--------------+-------+
  6. |  1 | 林磊儿       | 语文         |   148 |
  7. |  2 | 林磊儿       | 数学         |   150 |
  8. |  3 | 林磊儿       | 英语         |   147 |
  9. |  4 | 乔英子       | 语文         |   121 |
  10. |  5 | 乔英子       | 数学         |   106 |
  11. |  6 | 乔英子       | 英语         |   146 |
  12. |  7 | 方一凡       | 语文         |    70 |
  13. |  8 | 方一凡       | 数学         |    90 |
  14. |  9 | 方一凡       | 英语         |    59 |
  15. 10 | 方一凡       | 特长加分     |   200 |
  16. 11 | 陈哈哈       | 语文         |   109 |
  17. 12 | 陈哈哈       | 数学         |    92 |
  18. 13 | 陈哈哈       | 英语         |    80 |
  19. +----+--------------+--------------+-------+
  20. 13 rows in set (0.00 sec)

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

efc78f7069bff7eea8c24f2a2fea62c0.png

一、行转列SQL写法

方法一:使用case..when..then进行 行转列


   
  1. #来源公众号【码农编程进阶笔记】
  2. SELECT student_name,
  3.     SUM(CASE `subject` WHEN '语文' THEN score ELSE 0 END) as '语文',
  4.     SUM(CASE `subject` WHEN '数学' THEN score ELSE 0 END) as '数学',
  5.     SUM(CASE `subject` WHEN '英语' THEN score ELSE 0 END) as '英语',
  6.     SUM(CASE `subject` WHEN '特长加分' THEN score ELSE 0 END) as '特长加分' 
  7. FROM t_gaokao_score 
  8. 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()。

46ac8e51dfa90257782493f304d23ab7.png

方法二:使用IF()进行 行转列:


   
  1. #来源公众号【码农编程进阶笔记】
  2. SELECT student_name,
  3.     SUM(IF(`subject`='语文',score,0)) as '语文',
  4.     SUM(IF(`subject`='数学',score,0)) as '数学',
  5.     SUM(IF(`subject`='英语',score,0)) as '英语',
  6.     SUM(IF(`subject`='特长加分',score,0)) as '特长加分' 
  7. FROM t_gaokao_score 
  8. GROUP BY student_name;

  该方法将IF(subject='语文',score,0)作为条件,通过student_name进行分组,对分组后所有subject='语文’的记录的score字段进行SUM()操作,如果score没有值则默认为0。这种方式和case..when..then方法原理相同,相比更加简洁明了,建议使用。

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

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

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


   
  1. #来源公众号【码农编程进阶笔记】
  2. SELECT IFNULL(student_name,'总数') AS student_name,
  3.     SUM(IF(`subject`='语文',score,0)) AS '语文',
  4.     SUM(IF(`subject`='数学',score,0)) AS '数学',
  5.     SUM(IF(`subject`='英语',score,0)) AS '英语',
  6.     SUM(IF(`subject`='特长加分',score,0)) AS '特长加分',
  7.     SUM(score) AS '总数' 
  8. FROM t_gaokao_score
  9. GROUP BY student_name WITH ROLLUP;

查询结果:

c3ed03e683651b64f48f3e996cf4249b.png

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

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

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


   
  1. SELECT student_name,
  2. MAX(  
  3.         CASE subject  
  4.         WHEN '语文' THEN  
  5.             (  
  6.                 CASE  
  7.                 WHEN score - (select avg(score) from t_gaokao_score where subject='语文') > 20 THEN  
  8.                     '优秀'  
  9.                 WHEN score - (select avg(score) from t_gaokao_score where subject='语文') > 10 THEN  
  10.                     '良好'  
  11.                 WHEN score - (select avg(score) from t_gaokao_score where subject='语文') >= 0 THEN  
  12.                     '普通'  
  13.                 ELSE  
  14.                     '差'  
  15.                 END  
  16.             )  
  17.         END  
  18.     ) as '语文'
  19. MAX(  
  20.         CASE subject  
  21.         WHEN '数学' THEN  
  22.             (  
  23.                 CASE  
  24.                 WHEN score - (select avg(score) from t_gaokao_score where subject='数学') > 20 THEN  
  25.                     '优秀'  
  26.                 WHEN score - (select avg(score) from t_gaokao_score where subject='数学') > 10 THEN  
  27.                     '良好'  
  28.                 WHEN score - (select avg(score) from t_gaokao_score where subject='数学') >= 0 THEN  
  29.                     '普通'  
  30.                 ELSE  
  31.                     '差'  
  32.                 END  
  33.             )  
  34.         END  
  35.     ) as '数学',
  36. MAX(  
  37.         CASE subject  
  38.         WHEN '英语' THEN  
  39.             (  
  40.                 CASE  
  41.                 WHEN score - (select avg(score) from t_gaokao_score where subject='英语') > 20 THEN  
  42.                     '优秀'  
  43.                 WHEN score - (select avg(score) from t_gaokao_score where subject='英语') > 10 THEN  
  44.                     '良好'  
  45.                 WHEN score - (select avg(score) from t_gaokao_score where subject='英语') >= 0 THEN  
  46.                     '普通'  
  47.                 ELSE  
  48.                     '差'  
  49.                 END  
  50.             )  
  51.         END  
  52.     ) as '英语',
  53. SUM(score) as '总分',
  54. (CASE WHEN SUM(score) > 430 THEN '重点大学'  
  55.       WHEN SUM(score) > 400 THEN '一本'  
  56.       WHEN SUM(score) > 350 THEN '二本'  
  57.       ELSE '工地搬砖' 
  58.       END ) as '结果'
  59. FROM t_gaokao_score 
  60. GROUP BY student_name 
  61. ORDER BY SUM(score) desc;

我们来看一下输出结果:

fc1e67d02c520a2312dd403744c166ca.png

好了,SQL方面就是以上这些内容了,有疑问可以写在评论区留言!

48222a40894c5443426802e45a0b716f.png

文章来源: blog.csdn.net,作者:lxw1844912514,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/lxw1844912514/article/details/125383333

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。