MySQL之子查询

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 笔记

开发工具:

  • mysql-8.0
  • DataGrip

数据源:chapter13_user.csv

id,name,sex,class
E001,李明,男,一班
E002,张华,男,一班
E003,薛娟,女,二班

数据源:chapter13_score.csv

id,score,month_num
E001,687,1月
E002,667,1月
E003,686,1月
E001,616,2月
E002,699,2月
E003,503,2月
E001,596,3月
E002,622,3月
E003,593,3月


(1)子查询的分类


(1.1)select子查询

select子查询是指select后面是一个完整的select语句。比如,我们要获取每位同学每次月考的成绩与全部同学全部成绩的平均值。

select id,
       score,
       (select
               avg(score)
       from demo.chapter13_score) as avg_score
from demo.chapter13_score;
-- 窗口函数实现
select id,score,avg(score) over() as avg_score from demo.chapter13_score;

查询结果:

16.png

(1.2)from子查询

from子查询是指from后面是一个完整的select语句。比如,我们要获取每次月考中平均成绩在600分以上的同学的基本信息。

-- 方案一
select avg_table.id,
       avg_table.avg_score,
       chapter13_user.name,
       chapter13_user.sex,
       chapter13_user.class
from
     (select id,
             avg(score) as avg_score
     from demo.chapter13_score
     group by id
     having avg_score > 600) as avg_table
left join
         demo.chapter13_user
             on demo.chapter13_user.id = avg_table.id;
-- 方案二
select avg_table.id,
       avg_table.avg_score,
       chapter13_user.name,
       chapter13_user.sex,
       chapter13_user.class
from
     (select id,
             avg(score) as avg_score
     from demo.chapter13_score
     group by id
     ) as avg_table
left join
         demo.chapter13_user
             on demo.chapter13_user.id = avg_table.id
where avg_table.avg_score > 600;

运行上面的代码,具体运行结果如下表所示。

17.png


(1.3)where子查询

where子查询是指where后面是一个完整的select语句,用它查询出来的结果进行条件筛选。比如我们要把平均成绩大于600分的同学的每次月考成绩提取出来

select id,
       score,
       month_num
from demo.chapter13_score
where id in (select id
     from demo.chapter13_score
     group by id
     having avg(score)  > 600) ;

运行上面的代码,就会得到平均成绩大于600分的每位同学的每次月考成绩,具体运行结果如下表所示。

18.png 在where后面除了可以使用in,我们还可以使用>、<、!=等其他比较运算符,比如,我们要获取chapter13_score表中大于平均成绩的成绩记录,可以通过如下代码实现:

select id,
       score,
       month_num
from demo.chapter13_score
where score > (select avg(score)
     from demo.chapter13_score) ;

运行上面的代码,具体运行结果如下表所示。

19.png

我们要获取每个人几个月中成绩第二的数据

-- where子查询实现
select * from demo.chapter13_score
    as t1
where score = (select score
from demo.chapter13_score t2
where t1.id = t2.id
order by score
desc limit 1,1);
-- 窗口函数
select id,
       score,
       month_num
from (select id,
             score,
             month_num,
             row_number() over(partition by id order by score desc ) as rank_num
from demo.chapter13_score)
    as rank_table
where rank_num = 2;

20.png


(2)with建立临时表


from子查询语句本质上相当于建立了一张临时表,这种方法有一个缺点是如果我们要对子查询部分重复使用,此部分代码就需要重复执行,这样是很耗费时间和计算资源的。解决重复计算问题有两种办法:第一种就是在数据库中建立一张实际存在的表;第二种是在一段代码最开始部分建立一张临时表,然后在代码的后面部分可以一直调用这张临时表。我们这里主要讲一下第二种方法的实现,即通过with来建立临时表,建立临时表的这部分查询在同一个程序中只执行一次,并将查询结果存储在用户的临时表空间中,可以被多次使用,直到整个程序结束。


我们来举个例子,比如,我们现在要给每位同学的平均成绩加一个标签,大于600或小于600,我们可以通过子查询的方式先把平均成绩大于600分的同学筛选出来,然后加一个常数列大于600;再通过子查询的方式先把平均成绩小于600分的同学筛选出来,然后加一个常数列小于600;最后把上面的两张表通过union的形式连接起来。具体实现代码如下:

select id,
             avg(score) as avg_score,
       '大于600' as score_bin
     from demo.chapter13_score
     group by id
     having avg_score > 600
union all
select id,
             avg(score) as avg_score,
       '小于600' as score_bin
     from demo.chapter13_score
     group by id
     having avg_score < 600;

运行上面的代码,具体运行结果如下表所示。

21.png

用with建立临时表的实现代码如下:

-- with用法,创建临时表
with avg_score_table as (
    select id,
             avg(score) as avg_score
     from demo.chapter13_score
     group by id
)
select id,avg_score,'大于600' as score_bin from avg_score_table where avg_score > 600
union all
select id,avg_score,'小于600' as score_bin from avg_score_table where avg_score < 600;

with建立临时表的结构如下:

with临时表名as( 临时表建立语句部分 ) 
-- 开始正式查询 
select * from 临时表名

上面的演示中with只建立了一张临时表,我们还可以使用with同时建立多张临时表,结构如下:

with临时表名1 as( 临时表建立语句部分 ),
临时表名2 as( 临时表建立语句部分 ),  
临时表名3 as( 临时表建立语句部分 ), 
...... 临时表名n as( 临时表建立语句部分 ),
-- 开始正式查询 
select * from 临时表名

比如我们现在要获取男性同学的平均成绩,那么我们就可以先分别生成两张临时表,一张是每位同学的平均成绩表,另一张是男性信息表,然后将这两张表进行连接,且把性别(sex)字段为空的数据过滤掉即可,具体实现代码如下:

-- 比如我们现在要获取男性同学的平均成绩
-- 平均成绩
with avg_score_table as (
    select id,
           avg(score) as avg_score
    from demo.chapter13_score
    group by id
),
     -- 建立男性临时表
user_table as (
    select id,name,sex from chapter13_user where sex = '男'
    )
select user_table.id,
       user_table.name,
       user_table.sex,
       avg_score_table.avg_score
from user_table
    left join avg_score_table
        on avg_score_table.id = user_table.id;

运行上面的代码,具体运行结果如下表所示。

22.png



相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4天前
|
SQL 关系型数据库 MySQL
mysql子查询、聚合函数
mysql子查询、聚合函数
|
4天前
|
关系型数据库 MySQL
Mysql基础第十七天,使用子查询
Mysql基础第十七天,使用子查询
18 0
|
4天前
|
SQL 关系型数据库 MySQL
MySQL子查询篇(精选20道子查询练习题)-2
MySQL子查询篇(精选20道子查询练习题)
32 0
|
4天前
|
SQL 关系型数据库 MySQL
MySQL子查询篇(精选20道子查询练习题)-1
MySQL子查询篇(精选20道子查询练习题)
43 0
|
4天前
|
SQL 关系型数据库 MySQL
MySQL多表查询 子查询效率(DQL语句)
MySQL多表查询 子查询效率(DQL语句)
40 0
|
4天前
|
SQL 关系型数据库 MySQL
⑧【MySQL】数据库查询:内连接、外连接、自连接、子查询、多表查询
⑧【MySQL】数据库查询:内连接、外连接、自连接、子查询、多表查询
97 0
|
4天前
|
SQL 缓存 关系型数据库
MySQL调优之关联查询、子查询优化
MySQL调优之关联查询、子查询优化
380 0
|
4天前
|
SQL 数据库
mysql-相关子查询
该任务是找出未选修任何课程的学生学号和姓名。通过在教学数据库中使用SQL子查询,先获取选修了课程的学生学号集合,然后在外层查询中找出不在这个集合中的学生信息。代码实现为:`select sno, sname from student where sno not in (select distinct sno from score);`
19 0
|
4天前
|
数据库
mysql-相关子查询
任务是找出选修了课程004的学生姓名和所在系。在teachingdb数据库中,使用子查询和EXISTS关键字来实现。代码示例:`select sname, sdept from student a where exists (select * from score b where a.sno=b.sno and b.cno=004);`
11 0
|
4天前
|
关系型数据库 MySQL 数据库
MySQL -相关子查询
该任务是数据库查询,目标是找出所有选修了&quot;刘东明&quot;所选全部课程的学生学号。需运用子查询和NOT EXISTS运算符。代码首先选择学生表中名字不是&#39;刘东明&#39;的学生,然后检查他们是否存在与&#39;刘东明&#39;相同的所有课程记录。
18 0

推荐镜像

更多