欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流
本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle
在前一篇内容中,学习了MySQL的行列转换中的行转列,其中只讲述了在MySQL与Oracle中通欧诺个的行转列,并且进行了对应的扩展了——如果想在结果中加入学生姓名的方法,上一篇讲了其中一种方法,就是使用关联子查询。
今天这篇内容,将继续进行讲述MySQL的行列转换的后续内容,其中包括添加学生姓名的第二种方法(使用了join进行关联表),以及本文章主攻的核心内容——行列转换中的列转行。
同样的,为了大家可以更方便的一起跟着文章进行代码的操作学习,在文章中的每一块的知识点都提供了对应的数据准备,即大家可以直接复制代码在自己的电脑上进行建表,然后根据文章中的内容一起进行实操,因为我个人认为计算机方面的知识点的学习,实操相对于光进行文字的学习会更有效果,并且更容易发现自己的短板和思路中存在的问题。
那么,快拿出你的电脑,跟着文章一起学习起来吧
:传送门数据准备操作
:传送门1.1为何进行行转列?
:传送门1.2 行转列的两个意思
:传送门3.1如何进行行转列
:传送门4.1通用的行转列(Mysql和Oracle都能用)
:传送门4.1.1在结果中加入学生名字)
select distinct t1.user_name ,t0.* -- 如果不加distinct,因为t1表每个ID对应多个名字,所以最终结过就是,名字重复几次,结果就有几行重复
from
(
select
user_id '学生ID',
max(case when course = '语文' then score end) '语文',
max(case when course = '数学' then score end) '数学',
max(case when course = '英语' then score end) '英语'
from
table_grade
group by
user_id
) t0left join table_grade t1
on t0.学生ID = t1.user_id; -- 此处的t0.学生ID,因为前面设置了别名,所以此处也应该使用别名,不然就会发生错误:Unknown column 't0.user_id' in 'on clause'
select user_id '学生ID',
max(if(course = '语文',score,null)) '语文',
max(if(course = '数学',score,null)) '数学',
max(if(course = '英语',score,null)) '英语'
from table_grade
group by user_id
select user_id '学生ID',
(select max(user_name) from table_grade where table_grade.user_id =t.user_id ) user_name,
max(if(course = '语文',score,null)) '语文',
max(if(course = '数学',score,null)) '数学',
max(if(course = '英语',score,null)) '英语'
from table_grade t
group by user_id
select distinct t1.user_name,t0.*
from
( select user_id '学生ID',
max(if(course = '语文',score,null)) '语文',
max(case when course = '数学' then score end) '数学',
max(if(course = '英语',score,null)) '英语'
from table_grade
group by user_id ) t0
left join table_grade t1
on t0.学生ID = t1.user_id;
a b c
1 1 a
2 1 b
3 1 c
2 a
2 b
2 c
3 a
3 b
3 c
列转行如上图所示,左边变成右边
- 右图又称为纵表,这种纵表在大数据中适合用工具hbase进行列式存储,里面存的就是键值对,右图的左列是键、右列是值
- 纵表适合存储,横表适合分析
- 底层明细数据,适合列式存储
- select(查询)能表达的关系是并差交笛卡尔积
- 集合运算是 并差交笛卡尔积
- 关系运算是 投影连接除
- 大数据一次处理一个集合(set),不是一个记录(record)
建个横表
create table table_grade_wide as(
select user_id '学生ID',
max(if(course = '语文',score,null)) '语文',
max(if(course = '数学',score,null)) '数学',
max(if(course = '英语',score,null)) '英语'
from table_grade
group by user_id )
alter table table_grade_wide change user_id id int;
select * from(
select 学生ID,'语文' course,语文 score from table_grade_wide -- 只需要在第一个select字段中修改别名就好了,因为union的时候,前后的所有的select的列的类型和个数是一致的
union --
select 学生ID,'数学',数学 from table_grade_wide
union
select 学生ID,'英语',英语 from table_grade_wide ) a
where score is not null -- 因为有的同学只考了其中几门课
order by 1; -- 按照最后结果的第一列进行排序
好了,MySQL的行列转换到这里就要告一段落了,希望大家通过上一篇文章——行列转换(一)• MySQL版以及本篇文章的学习,应该对MySQL的行列转换有了了解,学习是永无止境的,接下来,我们会按照这样的方式为大家讲述Oracle中的行列转换,如果大家对于文章的内容、排版等各个方面有什么好的想法,都可以进行沟通交流,也希望我的博客中的内容能为大家在学习的道路上提供一点点助力,我们一起学习,一起进步