首页 > 数据库 >mysql 行转列和列转行

mysql 行转列和列转行

时间:2024-11-14 08:57:56浏览次数:1  
标签:语文 转行 userid 转列 score mysql tb SUM subject

一、行转列

1、使用case…when…then

2、使用SUM(IF()) 生成列

3、使用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行

4、使用SUM(IF()) 生成列,直接生成汇总结果,不再利用子查询

5、使用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total

6、动态查询列值不确定的情况

7、合并字段显示:group_concat()

二、列转行
————————————————

一、行转列
即将原本同一列下多行的不同内容作为多个字段,输出对应内容。
建表语句

DROP TABLE IF EXISTS tb_score;

CREATE TABLE tb_score(
id INT(11) NOT NULL auto_increment,
userid VARCHAR(20) NOT NULL COMMENT '用户id',
subject VARCHAR(20) COMMENT '科目',
score DOUBLE COMMENT '成绩',
PRIMARY KEY(id)
)ENGINE = INNODB DEFAULT CHARSET = utf8;


插入数据

INSERT INTO tb_score(userid,subject,score) VALUES ('001','语文',90);
INSERT INTO tb_score(userid,subject,score) VALUES ('001','数学',92);
INSERT INTO tb_score(userid,subject,score) VALUES ('001','英语',80);
INSERT INTO tb_score(userid,subject,score) VALUES ('002','语文',88);
INSERT INTO tb_score(userid,subject,score) VALUES ('002','数学',90);
INSERT INTO tb_score(userid,subject,score) VALUES ('002','英语',75.5);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','语文',70);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','数学',85);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','英语',90);
INSERT INTO tb_score(userid,subject,score) VALUES ('003','政治',82);


查询数据表中的内容(即转换前的结果)

SELECT * FROM tb_score


先来看一下转换后的结果:

 

可以看出,这里行转列是将原来的subject字段的多行内容选出来,作为结果集中的不同列,并根据userid进行分组显示对应的score。

1、使用case…when…then 进行行转列

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


2、使用IF() 进行行转列:

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


注意点:

(1)SUM() 是为了能够使用GROUP BY根据userid进行分组,因为每一个userid对应的subject="语文"的记录只有一条,所以SUM() 的值就等于对应那一条记录的score的值。

假如userid =‘001’ and subject=‘语文’ 的记录有两条,则此时SUM() 的值将会是这两条记录的和,同理,使用Max()的值将会是这两条记录里面值最大的一个。但是正常情况下,一个user对应一个subject只有一个分数,因此可以使用SUM()、MAX()、MIN()、AVG()等聚合函数都可以达到行转列的效果。

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

3、利用SUM(IF()) 生成列 + WITH ROLLUP 生成汇总行,并利用 IFNULL将汇总行标题显示为Total

SELECT IFNULL(userid,'total') AS 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 政治,
SUM(IF(`subject`='total',score,0)) AS total
FROM(
SELECT userid,IFNULL(`subject`,'total') AS `subject`,SUM(score) AS score
FROM tb_score
GROUP BY userid,`subject`
WITH ROLLUP
HAVING userid IS NOT NULL
)AS A
GROUP BY userid
WITH ROLLUP;


运行结果:

 

4、利用SUM(IF()) 生成列 + UNION 生成汇总行,并利用 IFNULL将汇总行标题显示为 Total

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 政治,
SUM(score) AS TOTAL
FROM tb_score
GROUP BY userid
UNION
SELECT 'TOTAL',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) FROM tb_score


运行结果:

 

5、利用SUM(IF()) 生成列,直接生成结果不再利用子查询

SELECT IFNULL(userid,'TOTAL') AS 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 政治,
SUM(score) AS TOTAL
FROM tb_score
GROUP BY userid WITH ROLLUP;


运行结果:

 

6、动态,适用于列不确定情况

SET @EE='';
select @EE :=CONCAT(@EE,'sum(if(subject= \'',subject,'\',score,0)) as ',subject, ',') AS aa FROM (SELECT DISTINCT subject FROM tb_score) A ;

SET @QQ = CONCAT('select ifnull(userid,\'TOTAL\')as userid,',@EE,' sum(score) as TOTAL from tb_score group by userid WITH ROLLUP');
-- SELECT @QQ;

PREPARE stmt FROM @QQ;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;


运行结果:

 

7、合并字段显示:利用group_concat()

SELECT userid,GROUP_CONCAT(`subject`,":",score)AS 成绩 FROM tb_score
GROUP BY userid


运行结果:

 

group_concat(),手册上说明:该函数返回带有来自一个组的连接的非NULL值的字符串结果。
比较抽象,难以理解。通俗点理解,其实是这样的:group_concat()会计算哪些行属于同一组,将属于同一组的列显示出来。要返回哪些列,由函数参数(就是字段名)决定。分组必须有个标准,就是根据group by指定的列进行分组。

结论:group_concat()函数可以很好的建属于同一分组的多个行转化为一个列。

二、列转行
建表语句:

CREATE TABLE tb_score1(
id INT(11) NOT NULL auto_increment,
userid VARCHAR(20) NOT NULL COMMENT '用户id',
cn_score DOUBLE COMMENT '语文成绩',
math_score DOUBLE COMMENT '数学成绩',
en_score DOUBLE COMMENT '英语成绩',
po_score DOUBLE COMMENT '政治成绩',
PRIMARY KEY(id)
)ENGINE = INNODB DEFAULT CHARSET = utf8;


插入数据:

INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('001',90,92,80,0);
INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('002',88,90,75.5,0);
INSERT INTO tb_score1(userid,cn_score,math_score,en_score,po_score) VALUES ('003',70,85,90,82);


查询数据表中的内容(即转换前的结果)

SELECT * FROM tb_score1


转换后:


本质是将userid的每个科目分数分散成一条记录显示出来。

直接上SQL:

SELECT userid,'语文' AS course,cn_score AS score FROM tb_score1
UNION ALL
SELECT userid,'数学' AS course,math_score AS score FROM tb_score1
UNION ALL
SELECT userid,'英语' AS course,en_score AS score FROM tb_score1
UNION ALL
SELECT userid,'政治' AS course,po_score AS score FROM tb_score1
ORDER BY userid


这里将每个userid对应的多个科目的成绩查出来,通过UNION ALL将结果集加起来,达到上图的效果。

标签:语文,转行,userid,转列,score,mysql,tb,SUM,subject
From: https://www.cnblogs.com/shujuyr/p/18545262

相关文章

  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现八
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • 《MYSQL45讲》误删数据怎么办
    对误删数据分类的话,有1.delete误删行2.droptable或者truncatetable语句误删表3.使用dropdatabase误删数据库4.使用rm命令误删整个MYSQL实例一,误删行一下操作前置条件是:binlog的格式是row,并且binglog_row_image是FULL,表示记录数据修改前后完整信息。如何恢复使......
  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现七
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • Windows平台下安装与配置MySQL5.7
    1.下载mysql安装文件下载地址:https://downloads.mysql.com/archives/installer/  2.安装与配置MySQL双击打开,接受许可协议,点击下一步:选择自定义安装,点击下一步:选择要安装的产品,点击下一步:点击执行按钮:安装完成,点击下一步进入配置界面:配置界面继续点击下一步:进......
  • mysql查询表列数
    1.使用DESCRIBE命令:DESCRIBE语句可以返回表的结构信息,包括列名、类型、键等。可以通过查询DESCRIBE的结果集的行数来得到表的列数。DESCRIBEtable_name;2.使用SHOWCOLUMNS命令:SHOWCOLUMNS语句可以显示指定表的列信息,包括列名、类型、键等。可以通过查询SHOWCOLUMNS的结果集的......
  • Docker安装MySQL双主从复制
    一、下载mysql镜像略二、主节点my.cnf配置[mysqld]设置server_id,同一局域网中需要唯一server_id=1指定不需要同步的数据库名称binlog-ignore-db=mysql开启二进制日志功能log-bin=mysql-bin设置二进制日志使用内存大小(事务)binlog_cache_size=1M设置使用的二进制日志......
  • MySQL JDBC
    在Java开发中,与数据库进行交互是不可或缺的一部分。MySQL作为一种流行的关系型数据库管理系统,与Java的集成通常通过JDBC(JavaDatabaseConnectivity)来实现。JDBC提供了一套用于执行SQL语句的API,使得Java程序能够连接和操作数据库。本文将深入探讨MySQL与JDBC的集成过程,包括驱动......
  • MySQL 数据库
    在当今数字化浪潮中,数据库作为企业级应用的核心组件,其重要性不言而喻。从关系型数据库到非关系型数据库,再到分布式数据库,技术的演进不断推动着企业级数据库开发向更高效、更可靠、更可扩展的方向发展。本文将深入探讨数据库企业级开发的关键技术,结合代码示例,为您呈现一个全面的......
  • mysql基础知识2
    登录mysql数据库注:文中mysql版本为8.0而并非5.7使用命令行登录在操作系统中打开命令行工具/或使用xshell等ssh登录使用命令行登录数据库:根据所使用的数据库类型,输入相应的命令行登录命令。mysql-u[用户名]-p[密码]-P3306-h[数据库地址]-u用户名-p密码-P端口-h......
  • mysql基础知识(3)
    MySQL中有哪些重要的日志文件?错误日志:记录MySQL服务器运行过程中的错误信息。查询日志(GeneralLog):记录数据库执行的所有命令。慢查询日志:记录执行时间超过预设阈值的查询语句。redolog(重做日志):用于在系统崩溃时恢复未提交的数据。undolog(回滚日志):用于事务回滚时恢复数......