sql之行转列和列转行

数据准备

CREATE TABLE `student_x` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `class` varchar(255) DEFAULT NULL,
  `score` int(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (1, '张三', '数学', 78);
INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (2, '张三', '英语', 93);
INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (3, '张三', '语文', 65);
INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (4, '李四', '数学', 87);
INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (5, '李四', '英语', 90);
INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (6, '李四', '语文', 76);
INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (7, '李四', '历史', 69);

行转列

-- 方法1
select name,
	max(case when class = '数学' then score else null end) as math_score,
	max(case when class = '英语' then score else null end) as engilsh_score,
	max(case when class = '语文' then score else null end) as chinese_score,
	max(case when class = '历史' then score else null end) as history_score
from student_x
group by name;
-- 方法2
select name,
	max(if(class = '数学', score, null)) as math_score,
	max(if(class = '英语', score, null)) as engilsh_score,
	max(if(class = '语文', score, null)) as chinese_score,
	max(if(class = '历史', score, null)) as history_score
from student_x
group by name;
-- 方法3
set @select_columns = ''; 
select @select_columns := concat(@select_columns,'sum(if(class= \'',class,'\',score,null)) as ',class, ',') as select_column 
from (
	select distinct class from student_x -- 统计去重后的科目名称集合
) as t; 

set @select_sql := 
concat('select name, ', substring(@select_columns, 1, char_length(@select_columns) - 1),' from student_x group by name;'); 
 
prepare stmt from @select_sql; -- 准备执行SQL语句
execute stmt; -- 执行SQL语句
deallocate prepare stmt; -- 释放变量资源

结果图:
在这里插入图片描述
**

列转行

CREATE TABLE `student_y` (
  `id` int(11) DEFAULT NULL, 
  `name` varchar(255) DEFAULT NULL,
  `math_score` bigint(255) DEFAULT NULL,
  `engilsh_score` bigint(255) DEFAULT NULL,
  `chinese_score` bigint(255) DEFAULT NULL,
  `history_score` bigint(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `student_y`(`id`, `name`, `math_score`, `engilsh_score`, `chinese_score`, `history_score`) VALUES (1, '张三', 78, 93, 65, NULL);
INSERT INTO `student_y`(`id`, `name`, `math_score`, `engilsh_score`, `chinese_score`, `history_score`) VALUES (2, '李四', 87, 90, 76, 69);
select * from (
	select name, 'math_score' as class, math_score as score from student_y
	union all
	select name, 'engilsh_score' as class, engilsh_score as score from student_y
	union all
	select name, 'chinese_score' as class, chinese_score as score from student_y
	union all
	select name, 'history_score' as class, history_score as score from student_y
) as x order by name,class;
CREATE TABLE `student_y2` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `scores` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `student_y2`(`id`, `name`, `scores`) VALUES (1, '张三', '78,93,65');
INSERT INTO `student_y2`(`id`, `name`, `scores`) VALUES (2, '李四', '87,90,76,69');
select 
	x.name,
	x.scores,
	char_length(x.scores) as length_scores,
	char_length(replace(x.scores, ',', '')) as length_scores_with_out_comma,
	char_length(x.scores) - char_length(replace(x.scores, ',', '')) + 1 as colum_num,
	substring_index(x.scores, ',', 1) as score1,
	substring_index(x.scores, ',', 2) as score12,
	substring_index(x.scores, ',', 3) as score123,
	substring_index(x.scores, ',', 4) as score1234,
	substring_index(substring_index(x.scores, ',', 1), ',', -1) as colum1,
	substring_index(substring_index(x.scores, ',', 2), ',', -1) as colum2,
	substring_index(substring_index(x.scores, ',', 3), ',', -1) as colum3,
	substring_index(substring_index(x.scores, ',', 4), ',', -1) as colum4
from student_y2 as x;
select 
	x.name,
	substring_index(substring_index(x.scores, ',', y.help_topic_id + 1), ',', -1) as 'score'
from student_y2 as x
join mysql.help_topic y
on y.help_topic_id < (length(x.scores) - length(replace(x.scores, ',', '')) + 1);
  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值