MySQL中列转行和行转列总结解决思路

目录
  • 引言
  • 列转行
  • 行转列
  • 总结

引言

在学习sql中遇到了列转行和行转列的题目,这里总结一下如何在对应的情景下解决不同的题目;

列转行

创建一个表stu_score_01:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for stu_score_01
-- ----------------------------
DROP TABLE IF EXISTS `stu_score_01`;
CREATE TABLE `stu_score_01` (
  `id` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  `chinese` varchar(255) DEFAULT NULL,
  `math` varchar(255) DEFAULT NULL,
  `english` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of stu_score_01
-- ----------------------------
BEGIN;
INSERT INTO `stu_score_01` VALUES ('1', '张三', '111', '109', '98');
INSERT INTO `stu_score_01` VALUES ('2', '李四', '89', '119', '109');
INSERT INTO `stu_score_01` VALUES ('3', '王五', '96', '102', '107');
INSERT INTO `stu_score_01` VALUES ('4', '小六', '56', '78', '88');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;

如果想要把这个表转为下面的形式:

+--------+---------+-------+
| name   | project | score |
+--------+---------+-------+
| 张三     | chinese | 111   |
| 李四     | chinese | 89    |
| 王五     | chinese | 96    |
| 小六     | chinese | 56    |
| 张三     | math    | 109   |
| 李四     | math    | 119   |
| 王五     | math    | 102   |
| 小六     | math    | 78    |
| 张三     | english | 98    |
| 李四     | english | 109   |
| 王五     | english | 107   |
| 小六     | english | 88    |
+--------+---------+-------+

那么就可以使用union或者union all来实现列转行操作:

select name, 'chinese' as project, chinese as score from stu_score_01
union all
select name, 'math' as project, math as score from stu_score_01
union all
select name, 'english' as project, english as score from stu_score_01;

简单解释一下:分别查询每一个科目的所有情况,求并集即可;比如单独执行一下sql:

select name, 'chinese' as project, chinese as score from stu_score_01;
#结果
+--------+---------+-------+
| name   | project | score |
+--------+---------+-------+
| 张三 	| chinese | 111   |
| 李四 	| chinese | 89    |
| 王五 	| chinese | 96    |
| 小六 	| chinese | 56    |
+--------+---------+-------+

接下来只需要一次类推求出所有情况集合求并即可;

union和union all都是求的表的并集,但是union会有去重和排序操作,效率低于union all,这里不需要去重,所以使用union all保证效率;

行转列

创建一个表stu_score_03:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for stu_score_03
-- ----------------------------
DROP TABLE IF EXISTS `stu_score_03`;
CREATE TABLE `stu_score_03` (
  `id` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  `project` varchar(255) DEFAULT NULL,
  `score` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of stu_score_03
-- ----------------------------
BEGIN;
INSERT INTO `stu_score_03` VALUES ('1', '张三', 'chinese', '111');
INSERT INTO `stu_score_03` VALUES ('10', '李四', 'english', '109');
INSERT INTO `stu_score_03` VALUES ('11', '王五', 'english', '107');
INSERT INTO `stu_score_03` VALUES ('12', '小六', 'english', '88');
INSERT INTO `stu_score_03` VALUES ('2', '李四', 'chinese', '89');
INSERT INTO `stu_score_03` VALUES ('3', '王五', 'chinese', '96');
INSERT INTO `stu_score_03` VALUES ('4', '小六', 'chinese', '56');
INSERT INTO `stu_score_03` VALUES ('5', '张三', 'math', '109');
INSERT INTO `stu_score_03` VALUES ('6', '李四', 'math', '119');
INSERT INTO `stu_score_03` VALUES ('7', '王五', 'math', '102');
INSERT INTO `stu_score_03` VALUES ('8', '小六', 'math', '78');
INSERT INTO `stu_score_03` VALUES ('9', '张三', 'english', '98');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;

如果想要单独把每一行科目分别转化为不同的列,如:

+--------+---------+------+---------+
| name   | chinese | math | english |
+--------+---------+------+---------+
| 小六 	| 56      | 78   | 88      |
| 张三 	| 111     | 109  | 98      |
| 李四 	| 89      | 119  | 109     |
| 王五 	| 96      | 102  | 107     |
+--------+---------+------+---------+

可以使用case…when和max/sum和group by来实现:

select name,
max(case when project = 'chinese' then score else 0 end) as 'chinese',
max(case when project = 'math' then score else 0 end) as 'math',
max(case when project = 'english' then score else 0 end) as 'english'
from stu_score_03
group by name;
# 或者使用sum
select name,
sum(case when project = 'chinese' then score else 0 end) as 'chinese',
sum(case when project = 'math' then score else 0 end) as 'math',
sum(case when project = 'english' then score else 0 end) as 'english'
from stu_score_03
group by name;

简单解释一下:

因为要查询每个人的不同科目成绩,所以需要对不同的人进行分组,所以需要使用group by,不然查出来的成绩谁都不知道知道是谁的;

对于每一个case when,比如:case when project = 'chinese' then score else 0 end

意思就是当project为chinese时获取score,否则就取0;其他也是一样的意思

还有为什么需要加上max或者sum,先想象一下如果不加上max或者sum会有什么样的效果:

因为先判断的是chinese科目,如果张三首先出现的科目是math,那么他先走chinese科目的判断,因为math不等于chinese,

所以给chinese科目赋值为0;

所以会看到如下效果:

select name,
case when project = 'chinese' then score else 0 end as 'chinese',
case when project = 'math' then score else 0 end as 'math',
case when project = 'english' then score else 0 end as 'english'
from stu_score_03
group by name;
#执行结果
+--------+---------+------+---------+
| name   | chinese | math | english |
+--------+---------+------+---------+
| 小六 	| 0       | 0    | 88      |
| 张三 	| 111     | 0    | 0       |
| 李四 	| 0       | 0    | 109     |
| 王五 	| 0       | 0    | 107     |
+--------+---------+------+---------+

因为小六最先出现的是english成绩,所以他的chinese和math成绩都被赋予值为0,

而张三最先出现的是chinese成绩,所以他的math和english成绩也被赋予值为0;

如果使用max或者sum,那么max会在出现的所有值的情况下(包括0)去最大的值,其实就是实际的分数,只是把0的情况去除了;

而sum是加上了所有值,因为除了实际分数外其他都是0,所以可以直接相加;

总结

说了这么多,其实可以总结两句话:

列转行,查询需要的每列数据使用union或者union all求并集

行转列,使用case…when分情况查询数据,group by和sum/max进行筛选

到此这篇关于MySQL中列转行和行转列总结解决思路的文章就介绍到这了,更多相关MySQL列转行和行转列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mysql 行转列和列转行实例详解

    mysql行转列.列转行 语句不难,不做多余解释了,看语句时,从内往外一句一句剖析 行转列 有如图所示的表,现在希望查询的结果将行转成列 建表语句如下: CREATE TABLE `TEST_TB_GRADE` ( `ID` int(10) NOT NULL AUTO_INCREMENT, `USER_NAME` varchar(20) DEFAULT NULL, `COURSE` varchar(20) DEFAULT NULL, `SCORE` float DEFAULT '0', PRIM

  • MySQL中列转行和行转列总结解决思路

    目录 引言 列转行 行转列 总结 引言 在学习sql中遇到了列转行和行转列的题目,这里总结一下如何在对应的情景下解决不同的题目: 列转行 创建一个表stu_score_01: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for stu_score_01 -- ---------------------------- DROP TABLE IF E

  • pandas如何优雅的列转行及行转列详解

    目录 一.列转行 1.背景描述 2.方法描述 2.1 方法1 2.2 方法2 2.3 方法3 2.4 方法4 3 思考与总结 4 思维延伸 4.1 例子1 4.2 例子2 二.行转列 1.准备数据 2.行转列实现 2.1 方法1 2.2 方法2 2.3 方法3 3.思考与总结 三.行列转换(长宽互换) 总结 一.列转行 1.背景描述 在日常处理数据过程中,你们可能会经常遇到这种类型的数据: 而我们用pandas进行统计分析时,往往需要将结果转换成以下类型的数据: 2.方法描述 准备数据 df =

  • python中pandas.DataFrame对行与列求和及添加新行与列示例

    本文介绍的是python中pandas.DataFrame对行与列求和及添加新行与列的相关资料,下面话不多说,来看看详细的介绍吧. 方法如下: 导入模块: from pandas import DataFrame import pandas as pd import numpy as np 生成DataFrame数据 df = DataFrame(np.random.randn(4, 5), columns=['A', 'B', 'C', 'D', 'E']) DataFrame数据预览: A

  • MySQL中Union子句不支持order by的解决方法

    本文实例讲述了MySQL中Union子句不支持order by的解决方法.分享给大家供大家参考,具体如下: 我对DB知之甚少,这问题只在MySQL遇到,不知道别的DBMS是不是也如此. 问题是这样的,我打算在一个表里获得与某一行记录相邻的两行,并且想通过union一起取出来,所以这么写: select id,title from subjects where id>#some_id# order by id limit 1 union select id,title from subjects

  • MySQL中show命令方法得到表列及整个库的详细信息(精品珍藏)

    show databases;show tables from db_name; show columns from table_name from db_name;show index from talbe_name [from db_name]; show status;show variables; show [full] processlist;show table status [from db_name]; show grants for user; 除了status,process

  • MySql中取前几行数据使用limit来完成

    在mysql中是没有top关键字的,在mysql中可以用limit来完成功能. order by id desc limit 10 按照id的倒序排序 取出前10条 order by id desc limit 0,10 按照id的倒序排序 取出前10条 order by id limit 5,10 按照id的正序排序 从第5条开始取10条 复制代码 代码如下: SELECT cat_id FROM shop_goods_type order by cat_id desc limit 1

  • mysql中RAND()随便查询记录效率问题和解决办法分享

    最近由于需要大概研究了一下MYSQL的随机抽取实现方法.举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1. 有两个方法可以达成以上效果. 1.新建一个表,里面存着 -5 至 5 之间的数.再利用order by rand()得到随机数. #建立指定范围数据表 复制代码 代码如下: #auther: 小强(占卜师) #date: 2008-03-31 create table r

  • MySQL中由load data语句引起死锁的解决案例

    一个线上项目报的死锁,简要说明一下产生原因.处理方案和相关的一些点. 1.背景 这是一个类似数据分析的项目,数据完全通过LOAD DATA语句导入一个InnoDB表中.为方便描述,表结构简化为如下: Create table tb(id int primary key auto_increment, c int not null) engine=innodb; 导入数据的语句对应为 Load data infile 'data1.csv' into table tb; Load data inf

  • MySql中的longtext字段的返回问题及解决

    目录 MySql中longtext字段的返回 如下图所示 解决方法 Mysql中Text字段的范围 汉字在utf8mb4中占用几个字符 MySql中longtext字段的返回 最近开发中用到了longtext这种字段.在mysql中该字段的最大长度为4G 如下图所示 开发中遇到的一个问题就是.例如有个article表,然后我们的页面要将数据以列表的形式展示到前端(只显示几个字段,如作者,标题等等,例如放到table中显示多条记录),但是是将该表中的所有信息都查出来,然后当用户点击某条记录的时候,

  • MySQL中Multiple primary key defined报错的解决办法

    创建主键可以有两种方式: create table 表名( 字段名 类型, 字段名 类型, -- primary key(name) ); 或者是 create table 表名( 字段名 类型 primary key, 字段名 类型, -- ); 但是要注意的是,想要创建复合主键,就不可以用第二种方式. 下面列举一个小例子: 这里报错Multiple primary key defined,表示定义了多个主键,正确的写法是如下: 如果项设置复合主键,复合主键的特点是同时创建.同时删除,所以需要

随机推荐