MySQL行转列与列转行,存储过程动态行转列

在这里插入图片描述

一、创建表插入一些示例数据

create table score(
	id bigint(20) auto_increment,
	sname varchar(255) comment "学生姓名",
	cname varchar(255) comment "课程名称",
	score int(11) comment "分数",
	primary key(id)
)engine=innodb;
insert into score values(1,"小孙","mysql",55);
insert into score values(2,"小孙","python",66);
insert into score values(3,"小孙","java",47);
insert into score values(4,"小郭","mysql",70);
insert into score values(5,"小郭","python",85);
insert into score values(6,"小林","java",67);
insert into score values(7,"小林","mysql",77);

查看下插入的数据
在这里插入图片描述

二、行转列

1. 概述、当学生人数较多时,不能更清晰的看出学生各个课程的成绩对比,进行行转列来看一哈。
方法1:
select sname,max(case cname when "java" then score end) java,
				max(case cname when "python" then score end) python,
					max(case cname when "mysql" then score end) mysql from score group by sname;

在这里插入图片描述

方法2:
select distinct a.sname,
(select score from score b where a.sname = b.sname and b.cname = "mysql") as mysql,
(select score from score b where a.sname = b.sname and b.cname = "python") as python,
(select score from score b where a.sname = b.sname and b.cname = "java") as java
from score a;

在这里插入图片描述

方法3:
运用存储过程动态的进行行转列
好处:
1. 不需要每次添加课程来调整SQL语句
2. 随时可以用call 函数来调用
3.较快的执行速度(在首次运行一个存储过程时,优化器对其进行分析,而批处理每次运行进行编译和优化,速度相对较慢)
4.通过存储过程的权限进行限制,能够实现对相应的数据访问权限限制,避免非授权用户数据的访问,保证数据的安全性。
drop procedure if exists sp_score;
delimiter &&  # 定义&& 为SQL结束语
create procedure sp_score()
begin
	# 课程名称
	declare cname_n varchar(20) ; # 定义课程字段cname_n
	declare count_ int ; # 定义循环条件(课程总量)
	declare i int default 0 ; # 拼接SQL字符串
	set @s = 'select sname' ; # 定义s变量为字符串前缀
	set count_ = (select count(distinct cname) from score); # 给count_赋值
	while i < count_ do
		set cname_n = ( 
			select cname from score group by cname limit i,1); # cname_n的值依次是每个课程名称
		set @s = concat(@s,", sum(case cname when ",'\"',cname_n,'\"'," then score else 0 end)"," as ",'\"',cname_n,'\"');
		select @s;
		set i = i +1;
		end
	while;
	set @s = concat(@s,' from score group by sname'); # 用于调试 select @s;
	PREPARE stmt
	FROM
		@s ; EXECUTE stmt ;
	END&&
delimiter ; # 将结束语调整为 ;
call sp_socre();

在这里插入图片描述

三、MySQL列转行

1. 创建表插入刚刚得出的数据进行列转行。
create table cname

	select sname,max(case cname when "java" then score end) java,
				max(case cname when "python" then score end) python,
					max(case cname when "mysql" then score end) mysql from score group by sname

在这里插入图片描述

2. 查出一门课程的所有学生成绩
select sname,"java" cname,java as score from cname;

在这里插入图片描述

3. 将所有学生的所有课程成绩列转行用union连接
select sname,"java" cname,java as score from cname
union select sname,"python" cname,python as score from cname
union select sname,"mysql" cname,mysql as score from cname
order by sname,cname;

在这里插入图片描述

4. 将上述结果集有NULL的值去掉
select * from (select sname,"java" cname,java as score from cname
union select sname,"python" cname,python as score from cname
union select sname,"mysql" cname,mysql as score from cname
order by sname,cname)a 
where a.score is not null;

在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像豆芽一样优秀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值