这是长表的样子
图片
这是宽表的样子
图片

-- 创建长表(用多行来描述一个学生的所有课程成绩)
-- create table score_long(
-- uid VARCHAR(10),
-- course varchar(20),
-- score INT
-- );

select * from score_long;

-- INSERT into score_long(uid,course,score) VALUES('zs','语文',100);
-- INSERT into score_long(uid,course,score) VALUES('zs','数学',90);
-- INSERT into score_long(uid,course,score) VALUES('zs','英语',80);
-- 
-- INSERT into score_long(uid,course,score) VALUES('ls','语文',200);
-- INSERT into score_long(uid,course,score) VALUES('ls','数学',290);
-- INSERT into score_long(uid,course,score) VALUES('ls','英语',280);

-- 行转列,把长表转成宽表,本来一个学生的成绩是用多行来描述的,转换后变成一个学生的成绩用一行多列来表示
-- 按uid分组后每一个uid会有多行数据,一行代表一个成绩,聚合函数可以把多行聚合成一行,所以使用聚合+if提取出每一个
-- 成绩的具体指,if的作用是为了辅助聚合,通过if保证聚合时只有特定课程有值其余都是0
select  
	uid,
  max(if(course='语文',score,0)) as '语文',
  max(if(course='数学',score,0)) as '数学',
  max(if(course='英语',score,0)) as '英语'
from score_long
GROUP BY uid;


-- 创建宽表(用一行来描述一个学生的所有课程成绩)
create table score_wide(
uid varchar(10),
`语文` int,
`数学` int ,
`英语` int
);

-- 列转行,宽表转长表,把用一行描述的成绩变成用多行描述,使用union实现
-- 需求是把每一列的数据转成行,所以在每一个union中提取出某个特定列,然后用union连接到一起
insert into score_wide(uid,`语文`,`数学`,`英语`) values ('zs',100,90,80);
insert into score_wide(uid,`语文`,`数学`,`英语`) values ('ls',200,290,280);

select * from score_wide

select uid,'语文' as course,`语文` as score
from 
score_wide
union
select uid,'数学' as course,`数学` as score
from 
score_wide
union
select uid,'英语' as course,`英语` as score
from 
score_wide