首页 > 数据库 >MySQL数据行怎么转为列

MySQL数据行怎么转为列

时间:2023-02-09 11:05:25浏览次数:30  
标签:语文 转为 SUM userid tb score MySQL 数据 subject

阅读目录

行转列

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

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

mysql> select * from tb_score;
+----+--------+---------+-------+
| id | userid | subject | score |
+----+--------+---------+-------+
|  1 | 001    | 语文    |    90 |
|  2 | 001    | 数学    |    92 |
|  3 | 001    | 英语    |    80 |
|  4 | 002    | 语文    |    88 |
|  5 | 002    | 数学    |    90 |
|  6 | 002    | 英语    |  75.5 |
|  7 | 003    | 语文    |    70 |
|  8 | 003    | 数学    |    85 |
|  9 | 003    | 英语    |    90 |
| 10 | 003    | 政治    |    82 |
+----+--------+---------+-------+
10 rows in set (0.00 sec)

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

+--------+--------+--------+--------+--------+
| userid | 语文   | 数学   | 英语   | 政治   |
+--------+--------+--------+--------+--------+
| 001    |     90 |     92 |     80 |      0 |
| 002    |     88 |     90 |   75.5 |      0 |
| 003    |     70 |     85 |     90 |     82 |
+--------+--------+--------+--------+--------+
3 rows in set (0.00 sec)

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;

注意点:

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

假如 userid ='001' and subject='语文' 的记录有两条,则此时 SUM() 的值将会是这两条记录的和,同理,使用 Max() 的值将会是这两条记录里面值最大的一个。

但是正常情况下,一个 user 对应一个 subject 只有一个分数,因此可以使用 SUM()MAX()、MIN()、AVG() 等聚合函数都可以达到行转列的效果。

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;
+--------+--------+--------+--------+--------+-------+
| userid | 语文   | 数学   | 英语   | 政治   | total |
+--------+--------+--------+--------+--------+-------+
| 001    |     90 |     92 |     80 |      0 |   262 |
| 002    |     88 |     90 |   75.5 |      0 | 253.5 |
| 003    |     70 |     85 |     90 |     82 |   327 |
| total  |    248 |    267 |  245.5 |     82 | 842.5 |
+--------+--------+--------+--------+--------+-------+
4 rows in set, 2 warnings (0.00 sec)

IFNULL() 函数

IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL 则返回第一个参数的值。

实例

第一个参数为 NULL:
SELECT IFNULL(NULL, "RUNOOB");
以上实例输出结果为:RUNOOB

第一个参数不为 NULL:
SELECT IFNULL("Hello", "RUNOOB");
以上实例输出结果为:Hello

WITH ROLLUP

当需要对数据库数据进行分类统计的时候,往往会用上 groupby 进行分组。
而在 groupby 后面还可以加入 withcubewithrollup 等关键字对数据进行汇总。

SELECT
	IFNULL(SUBJECT, "统计") as total,
	SUM(score) AS score
FROM
	tb_score
GROUP BY
	SUBJECT WITH ROLLUP;
+--------+-------+
| total  | score |
+--------+-------+
| 政治   |    82 |
| 数学   |   267 |
| 英语   | 245.5 |
| 语文   |   248 |
| 统计   | 842.5 |
+--------+-------+
5 rows in set (0.00 sec)

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;
+--------+--------+--------+--------+--------+-------+
| userid | 语文   | 数学   | 英语   | 政治   | TOTAL |
+--------+--------+--------+--------+--------+-------+
| 001    |     90 |     92 |     80 |      0 |   262 |
| 002    |     88 |     90 |   75.5 |      0 | 253.5 |
| 003    |     70 |     85 |     90 |     82 |   327 |
| TOTAL  |    248 |    267 |  245.5 |     82 | 842.5 |
+--------+--------+--------+--------+--------+-------+
4 rows in set (0.00 sec)

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;
+--------+--------+--------+--------+--------+-------+
| userid | 语文   | 数学   | 英语   | 政治   | TOTAL |
+--------+--------+--------+--------+--------+-------+
| 001    |     90 |     92 |     80 |      0 |   262 |
| 002    |     88 |     90 |   75.5 |      0 | 253.5 |
| 003    |     70 |     85 |     90 |     82 |   327 |
| TOTAL  |    248 |    267 |  245.5 |     82 | 842.5 |
+--------+--------+--------+--------+--------+-------+
4 rows in set, 1 warning (0.00 sec)

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

SELECT
	userid,
	GROUP_CONCAT(`subject`, ":", score) AS 成绩
FROM
	tb_score
GROUP BY
	userid;
+--------+-----------------------------------------+
| userid | 成绩                                    |
+--------+-----------------------------------------+
| 001    | 语文:90,数学:92,英语:80                 |
| 002    | 英语:75.5,数学:90,语文:88               |
| 003    | 语文:70,数学:85,英语:90,政治:82         |
+--------+-----------------------------------------+
3 rows in set (0.00 sec)

group_concat(),手册上说明:该函数返回带有来自一个组的连接的非 NULL 值的字符串结果。

比较抽象,难以理解。通俗点理解,其实是这样的:group_concat()会计算哪些行属于同一组,将属于同一组的列显示出来。要返回哪些列,由函数参数(就是字段名)决定。分组必须有个标准,就是根据group by指定的列进行分组。

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

环境

本教程操作环境:windows10系统

C:\Users\Administrator>mysql --version
mysql  Ver 14.14 Distrib 5.6.29, for Win64 (x86_64)

建表语句

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);

标签:语文,转为,SUM,userid,tb,score,MySQL,数据,subject
From: https://blog.51cto.com/u_13571520/6046059

相关文章

  • JavaScript 运算符数据类型
    阅读目录运算符1、自增运算符2、分别赋值3、求多次方4、js中逻辑运算符数据类型1、数据类型2、强制类型转换运算符1、自增运算符leta=11;aler......
  • delphi "数据库有数据,设计时也有数据,但是运行时没有数据"
    今天遇到个问题,设计时,[审核人]字段是有数据的 数据库里的[审核人]字段也是有数据的   但是偏偏运行时没有数据  首先排除字段绑定问题,因为设计阶......
  • mysql分组排序
    mysql的分组排序在实际应用中是经常用到的之前用pgsql的时候是有窗口函数来实现的,非常方便row_number()over(partitionby分组字段orderby排序字段desc)但是现......
  • 数据库事务
    什么是事务?转账是生活中常见的操作,比如从A账户转账100元到B账号。站在用户角度而言,这是一个逻辑上的单一操作,然而在数据库系统中,至少会分成两个步骤来完成:1.将A账户的......
  • 地图用得好,数据更直观!bi软件都有哪些地图图表?
    地图图表的使用频率有多高?每次做分析报告十有八九都要用到它。但不同情况下所需的地图图表往往不同,这就要求bi数据可视化软件能够提供更加多多样化的地图图表。bi数据可视化......
  • Response-输出字符数据、输出字节数据
    Response-输出字符数据服务器输出字符数据到浏览器步骤:1.获取字符输出流2.输出数据注意:乱码问题......
  • 软件测试之测试数据
    测试数据的准备是软件测试过程中非常重要的一个环节,功能测试、自动化测试、性能测试都避不开测试数据的准备工作。想要成长为一名优秀的测试工程师,非常有必要深入......
  • 解决resultMap映射数据错误的问题
    目录resultMap映射数据错误解决方案【报错】resultMap认知错误附图(修改过后的) resultMap映射数据错误mapper文件使用了resultMap进行一对多关系映射,不管怎么......
  • yum 安装MySql8.0
    一、下载官方YUM仓库https://dev.mysql.com/downloads/repo/yum/    二、登陆Linux服务器用Wgethttps://dev.mysql.com/get/mysql80-community-release-el8-......
  • 图形学数据结构 half-edge
    这个东西,看了之后只有一个感觉WC你看了之后,很可能会感觉 俺也一样这是​​https://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml​​介绍是用来精细化......