前提 我使用的是mysql
行转列
行转列(pivot)是用于改变数据表格布局的概念,改变数据的呈现方式。 我看到别人博主在描述行转列的时候,大致的思路是 行转列是一个拆分的过程,一行数据想要作为多行数据进行展示,只能拆开来,而MySQL中可以将数据分开的做法中就有一个思想 分组(group by)。
初步分析,在我的理解中,所谓行转列就是将列值旋转为列名。在我看来这个,一组数据的对应关系是不会发生变化的,毕竟是一个二维平面,在第一组数据(张一 科目一 90),你通过(张一 科目一) 这个横竖交叉值就是90,你通过(张一 90) 这个横竖交叉值就是科目一。比如,我现在要将以user_name为行,以study_subject为列 这两个作为X轴,Y轴,那么第一象限中的所有坐标都是score的值。
改为
现在,以study_subject作为列,而列是不会重复的,所以列名是study_subject的set集合(也就是不重复数据)。
现在情况就明确了,我现在知道行与列,通过分组,行就合并了,实际上只关心列名。 网上我看到了两种做法 1、使用case…when…then 2、使用SUM(IF()) 生成列 实际上,这两个方法严格上说是一个方法的两种写法(就是if else的判断)。
1、使用case…when…then 进行行转列
SELECT user_name,
SUM(CASE study_subject WHEN '科目一' THEN score ELSE 0 END) as '科目一',
SUM(CASE study_subject WHEN '科目二' THEN score ELSE 0 END) as '科目二',
SUM(CASE study_subject WHEN '科目三' THEN score ELSE 0 END) as '科目三',
SUM(CASE study_subject WHEN '科目四' THEN score ELSE 0 END) as '科目四'
FROM temporary
GROUP BY user_name;
# SUM(CASE study_subject WHEN '科目一' THEN score ELSE 0 END) as '科目一' 就是 查询对应人员科目一的分数总和,没有就为0 作为科目一的列
SUM()就是为了多合一,当然MAX()、MIN()、AVG()等这些都行。
2、使用IF() 进行行转列
SELECT user_name,
SUM(IF(study_subject='科目一',score,0)) as '科目一',
SUM(IF(study_subject='科目二',score,0)) as '科目二',
SUM(IF(study_subject='科目三',score,0)) as '科目三',
SUM(IF(study_subject='科目四',score,0)) as '科目四'
FROM temporary
GROUP BY user_name;
# if的三元运算
同样,SUM()就是为了多合一,当然MAX()、MIN()、AVG()等这些都行。
建表SQL
DROP TABLE IF EXISTS temporary;
create table temporary
(
id int auto_increment
primary key,
user_name varchar(20) not null comment '用户名称',
study_subject varchar(20) null comment '学习科目',
score double null comment '学科成绩'
)
charset = utf8mb3;
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (1, '张一', '科目一', 90);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (2, '张一', '科目二', 92);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (3, '张一', '科目三', 80);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (4, '张二', '科目一', 88);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (5, '张二', '科目二', 90);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (6, '张二', '科目三', 85);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (7, '张二', '科目四', 43);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (8, '张三', '科目一', 70);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (9, '张三', '科目二', 90);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (10, '张三', '科目三', 82);
INSERT INTO testtemp.temporary (id, user_name, study_subject, score) VALUES (11, '张三', '科目四', 67);
列转行
列转行 就是倒着来,之前不是分组将行数压缩了吗,现在就直接解开。说白了,就一列一列的展示。
我理解的列转行 就是逆向的 就是从1,1坐标开始 一直到结束 每一个坐标都表现出来。
变回
这里就只是挨个输出,就不写那个sql了(主要是不想去创建表,我确实太懒了)
SELECT id,user_name,...... FROM tb_xxxxx
UNION ALL
SELECT id,user_name,...... FROM tb_xxxxx
UNION ALL
SELECT id,user_name,...... FROM tb_xxxxx
UNION ALL
SELECT id,user_name,...... FROM tb_xxxxx
ORDER BY id
挨着输出就行了。