MySQL将多列转行

这篇博客探讨了一道面试题,即如何在MySQL中将多列数据按用户名汇总,实现了行转列的需求。作者提供了两种解决方案:使用CASE WHEN语句和通过PIVOT函数。文章指出,虽然PIVOT在Oracle中常见,但在MySQL中,CASE WHEN可能更快,因为它不需要创建临时表。同时,作者提到全表扫描在PIVOT实现中难以避免,对于性能有所影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

在这里插入图片描述

于是屁颠屁颠跑去建表准备数据挑战一下,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()函数改编的,全表扫描是避免不了的,不要指望加什么索引进行优化了,其实我内心还是比较拒绝这道题的!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值