建表
create table test_score ( id int null, uid varchar(20) null, course varchar(20) null, score int null ); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (1, 'tom', 'chinese', 89); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (2, 'jetty', 'math', 78); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (3, 'tom', 'english', 88); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (4, 'jetty', 'chinese', 89); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (5, 'jack', 'chinese', 90); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (6, 'jack', 'english', 78); INSERT INTO `spring-boot-bpmn`.test_score (id, uid, course, score) VALUES (7, 'jack', 'math', 99);
思路 sum+if
- 在长表的数据组织结构中,同一 uid 对应了多行,即每门课程一条记录,对应一组分数,而在宽表中需要将其变成同一 uid 下仅对应一行
- 在长表中,仅有一列记录了课程成绩,但在宽表中则每门课作为一列记录成绩
由多行变一行,那么直觉想到的就是要 groupby 聚合;由一列变多列,那么就涉及到衍生提取;
既然要用 groupby 聚合,那么就涉及到将多门课的成绩汇总,但现在需要的不是所有成绩汇总,而仍然是各门课的独立成绩,所以需要用一个 if 函数加以筛选提取;当然,用 case when 也可以;
- 在 if 筛选提取的基础上,针对不同课程设立不同的提取条件,并最终加一个聚合函数提取该列成绩即可。
sql代码
select uid, sum(if(course = 'chinese', score, null)) as 'chinses', sum(if(course = 'math', score, null)) as 'math', sum(if(course = 'english', score, null)) as 'english' from test_score group by uid;
宽表