建表:
成绩表:表名score,列名:学号、课程号、成绩
CREATE TABLE `score` (
`s_id` varchar(20) NOT NULL,
`c_id` varchar(20) NOT NULL,
`s_score` int(3) DEFAULT NULL,
PRIMARY KEY (`s_id`,`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入数据脚本:
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);
表数据如下图:
![](https://github.com/AlgoricLi/MyImage/blob/master/Mysql/%E8%A1%8C%E8%BD%AC%E5%88%97%E6%A1%88%E4%BE%8B/%E5%88%97%E4%BC%A0%E8%A1%8C%E5%9B%BE1.png?raw=true)
要求将该表行转列形成以下结构:
![](https://github.com/AlgoricLi/MyImage/blob/master/Mysql/%E8%A1%8C%E8%BD%AC%E5%88%97%E6%A1%88%E4%BE%8B/%E5%88%97%E8%BD%AC%E8%A1%8C%E5%9B%BE2.png?raw=true)
思路:
1. 使用常量列输出目标表的结构
SELECT s_id, '01', '02', '03' from score;
![](https://github.com/AlgoricLi/MyImage/blob/master/Mysql/%E8%A1%8C%E8%BD%AC%E5%88%97%E6%A1%88%E4%BE%8B/%E5%88%97%E8%BD%AC%E8%A1%8C%E5%9B%BE3.png?raw=true)
2. 使用case when表达式,替换常量列为对应的成绩
遍历score每一行,遇到不同的cid,将其值利用case/when转换成对应列的成绩
select s_id,
(case c_id when '01' THEN s_score ELSE 0 end) as '01',
(case c_id when '02' then s_score ELSE 0 end) as '02',
(case c_id when '03' then s_score ELSE 0 end) as '03'
from score;
![](https://github.com/AlgoricLi/MyImage/blob/master/Mysql/%E8%A1%8C%E8%BD%AC%E5%88%97%E6%A1%88%E4%BE%8B/%E5%88%97%E8%BD%AC%E8%A1%8C%E5%9B%BE4.png?raw=true)
经过上述转换后和最终结果很接近,但是s_id存在很多重复行,可以将其聚合成一行数据,这时很容易想到使用s_id分组,同时我们需要取出c_id在相同s_id下最大值,填入新的行即可
3.分组,求最大值
select s_id,
max(case c_id WHEN '01' then s_score else 0 end) '01',
max(case c_id WHEN '02' then s_score else 0 end) '02',
max(case c_id WHEN '03' then s_score else 0 end) '03'
FROM score
GROUP BY s_id
最后得到上面要求的结果:
![](https://github.com/AlgoricLi/MyImage/blob/master/Mysql/%E8%A1%8C%E8%BD%AC%E5%88%97%E6%A1%88%E4%BE%8B/%E5%88%97%E8%BD%AC%E8%A1%8C%E5%9B%BE2.png?raw=true)