MySQL将多列转行

一年没有写过复杂SQL,今天偶然在群里看到一条面试题:将一张课程成绩表里的成绩按照用户名进行汇总。具体汇总还是用图更一目了然:

MySQL将多列转行_第1张图片

于是屁颠屁颠跑去建表准备数据挑战一下,sql如下:

create table t_user_score(
	id int unsigned primary key auto_increment,
	user_name varchar(16),
	course_name varchar(32),
	score double 

);


insert into 
t_user_score(user_name, course_name, score)
VALUES 
('张三', '数学', 34),
('张三', '语文', 58),
('张三', '英语', 58),

('李四', '数学', 45),
('李四', '语文', 87),
('李四', '英语', 45),

('王五', '数学', 76),
('王五', '语文', 34),
('王五', '英语', 89)
;



看到这个需求,心里想:“这东西就不能直接查出来然后再业务代码中进行统计吗,毕竟是面试题,也没办法。”

思路: 这种凭空多出几列的好像 join 能做,因此写出了以下代码:

select m.user_name, m.score, m1.score, m2.score
from t_user_score as m 
left join t_user_score as m1 on m.user_name = m1.user_name
left join t_user_score as m2 on m.user_name = m2.user_name
where m.course_name = '数学' 
and m1.course_name = '语文' 
and m2.course_name = '英语'

选用 left join 原因是:

  • MySQL中连接查询不需要建立临时表,查询速度会比子查询快

在这里插入图片描述

运行一番的确可以达到行转列的目的。然后偷偷去搜索一下其他人是怎样实现行转列的,结果看到的大多数使用case when实现的,实现代码如下:

select t.user_name, max(math) as math, max(chinese) as chinese, max(english) as english
from (
	select user_name,
	case 
		when course_name = '数学' then score
	end as math,

	case 
		when course_name = '语文' then score
	end as chinese,

	case 
		when course_name = '英语' then score
	end  as english	
	from t_user_score
) as t
group by t.user_name
;

该实现是基于Oracle的decode()函数改编的,全表扫描是避免不了的,不要指望加什么索引进行优化了,其实我内心还是比较拒绝这道题的!

你可能感兴趣的:(数据库,mysql)