MySQL中的子查询用法

子查询

导入知识
1.select字句的构成
select …
from …
where …
group by
having …
order by

子查询

1.子查询是什么?
查询里面嵌套查询,也就是select里面还有select
select …(select)
from …(select)
where …(select)
group by
having …(select)
order by
嵌套的select字句可能出现在以上位置

2.子查询语法
子查询(inner query)先执行,然后执行主查询(outer query)
子查询返回的结果被用于外部查询中
子查询可出现在几乎所有的SELECT子句中,如:SELECT子句、FROM子句、WHERE子句、ORDER BY子句、HAVING子句等
子查询必须放在小括号中
子查询一般放在比较操作符的右边,以增强代码可读性

3.子查询分类
不相关子查询
子查询中没有使用到外部查询的表中的任何列。先执行子查询,然后执行外部查询
相关子查询(correlated subquery)
子查询中使用到了外部查询的表中的任何列。先执行外部查询,然后执行子查询
以上两种类型之下又可以分为:
行子查询(row subquery):返回的结果集是 1 行 N 列
列子查询(column subquery):返回的结果集是 N 行 1列
表子查询(table subquery):返回的结果集是 N 行 N 列
标量子查询(scalar subquery):返回1行1列一个值

标量子查询
1.标量子查询(scalar subquery):返回1行1列一个值
可以使用 = > < >= <= <> 操作符对子查询的结果进行比较

2.那么什么时候会用到子查询呢?
(1)我们在写select字句时,发现需要写多条select字句才能得到结果,并且这多条select字句之间有依赖关联的关系,依赖关系一般书写在select后边和where后边,这时我们就将多条select字句合起来写。
例如:以两条select字句为例:第一个select字句依赖第二个select字句的执行结果,我们就将使用子查询

示例1:(1)select name from PLAYERS where PLAYERNO=(select PLAYERNO from TEAMS where TEAMNO=1);
(2)select PLAYERNO from TEAMS where TEAMNO=1;
select name from PLAYERS where PLAYERNO=6;
(1)和(2)的结果是一样的
在这里插入图片描述示例2:
SELECT playerno,name,joined - (SELECT joined FROM players WHERE playerno=104) year_interval
##标量子查询,起了别名为 year_interval
FROM players
WHERE playerno < 60;
语句释义:对于编号小于60的球员,得到他们加入俱乐部的年份和104号球员加入俱乐部的年份之间的差值在这里插入图片描述示例3:
SELECT playerno,NAME
FROM players
WHERE birth_date < ( ##标量子查询,小于,大于,等于等比较符一般在where后执行;+,-等运算符一般在where字句之前执行
SELECT birth_date
FROM players
WHERE leagueno=‘6524’);
语句释义:查询生日小于联盟队员编号为9999的球员生日的球员的编号和姓名在这里插入图片描述
行子查询(多列单行)
行子查询(row subquery):返回的结果集是 1 行 N 列
使用行表达式进行比较,可以使用 = > < >= <= <> in操作符
示例:
SELECT name,sex,town,playerno ##查询name列,sex列,town列和player列
FROM players
WHERE (sex,town) = (SELECT sex, town ##行子查询,sex和town等于select的值
FROM players
WHERE playerno=104)
and playerno!=104 ##将等于104的过滤掉

语句示例:查询和104号球员性别相同并且住在同一城市的球员的编号在这里插入图片描述列子查询(单行多列)
1.列子查询(column subquery):返回的结果集是 N 行 1列
2.必须使用 IN、ANY 和 ALL 操作符对子查询返回的结果进行比较。其中, ANY 和 ALL 操作符不能单独使用,其前面必须加上单行比较操作符= > < >= <= <>
3.<=all(结果集) 释义为小于等于所有的,也就是求最小的 此外还有<all,>all,>=all等

any(结果集) 释义为大于里面任何一个即可,也就是大于最小的,此外还有<any,<=any,>=any等

扫描二维码关注公众号,回复: 6649492 查看本文章

4.什么时候用到列子查询??
(1)一个需求需要多个sql(select)
(2)几个select之间需要互相依赖

示例1:
SELECT playerno,NAME
FROM PLAYERS
WHERE playerno IN ( ##playerno in(SELECT字句查询到的单行多列数据)
SELECT playerno
FROM matches);

语句释义:查询至少参加了一场比赛的球员的编号和姓名
注:球员参加比赛表(matches表)里只有球员编号,球员名字在球员表中,所以在查询时会用到多个select语句,可以使用列子查询

示例2:
SELECT playerno,NAME,birth_date
FROM PLAYERS
WHERE birth_date <=ALL ( ##<=all释义为小于等于所有的,后边是一个多行一列的结果集
SELECT birth_date
FROM PLAYERS);
语句释义:查询那些最老的球员的编号、姓名和生日。最老的球员指的是出生日期小于等于 所有其它球员的球员

示例3:
SELECT playerno,NAME,birth_date
FROM players
WHERE birth_date >ANY (   ##大于结果集的任何一个
SELECT birth_date
FROM players);
语句释义:查询除了最老的球员之外,所有其它球员的编号、姓名和生日

5.注意:如果子查询的结果集中有null值,使用>ALL 和not in操作符时,必须去掉子查询结果集中的null值,否则查询结果错误
我们可以在结果集中使用where语句将null值过滤掉
示例:
SELECT leagueno,playerno
FROM players
WHERE leagueno >=ALL (
SELECT leagueno
FROM players
WHERE leagueno IS NOT NULL); ##在结果集中使用where语句将null值过滤
在这里插入图片描述此外,在使用not in也是将结果集的null值过滤

表子查询(多行多列)
1.表子查询(table subquery):返回的结果集是 N 行 N 列
必须使用 IN、ANY 和 ALL 操作符对子查询返回的结果进行比较
示例:
SELECT *
FROM committee_members
WHERE (begin_date,end_date) IN ( ##in后边的结果集可以是一列多行,where后可以是多列,是表子查询(多行多列)
SELECT begin_date,end_date
FROM committee_members
WHERE position=‘Secretary’);
语句释义:在committee_members表中,得到任职日期和卸任日期与具有Secretary职位的一行相同的所有行

内联视图
用在from子句中的子查询叫做内联视图(inline view)。它用作一个数据源,外部查询再从其中检索行
内联视图必须要定义别名,否则出错
示例:
SELECT playerno
FROM (SELECT playerno,sex ##()里面的我们称为内联视图
FROM players
WHERE playerno < 10) AS player10 ##as的作用是起别名,此外还要注意select和where
后的列名必须出现在子查询中(该示例是PLAYERNO和sex)
WHERE sex=‘M’;
语句释义:得到编号小于10的男性球员的编号

子查询中再嵌套子查询
示例:
SELECT playerno
FROM
(SELECT playerno, sex
FROM
(SELECT playerno, sex, joined
FROM
(SELECT playerno, sex, joined
FROM players
WHERE playerno > 10) great10
WHERE playerno < 100) less100
WHERE joined > 1980) joined1980
WHERE sex = ‘M’ ;

注:对于select字句来说,执行顺序是先执行子查询,子查询里又嵌套子查询时,先执行最里面的子查询,例如上述示例先执行绿色,在执行黄色,在执行蓝色,最后执行无颜色部分的select字句。

相关子查询
1.相关子查询(correlated subquery)
子查询中使用到了外部查询的表中的任何列。先执行外部查询,然后执行子查询

2.相关子查询的执行步骤
1)、先执行外部查询,得到的行叫做候选行
2)、使用某个候选行来执行子查询
3)、使用子查询的返回值来决定该候选行是出现在最终的结果集中还是被丢弃
4)、重复以上步骤2和3,将所有的候选行处理完毕,得到最终的结果

注:子查询的where条件中有主查询的列
示例:
SELECT matchno,playerno,teamno
FROM matches m ##别名m
WHERE playerno = (
SELECT playerno
FROM teams t ##别名t
WHERE playerno = m.playerno);
语句释义:对于球队的队长参加的每场比赛,得到比赛编号、队长编号和球队编号
语句分析:就是拿着外查询的结果去比较内查询的结果,如果两个结果相符,则保留结果,否则将结果摒弃

什么时候使用相关子查询?
(1)需要使用子查询
(2)两个子查询都不能独立执行

EXISTS操作符
1.该操作符专门判断子查询的结果集是否不为空:如果不为空则返回true,否则返回false
也就是exists操作符只考虑是否返回数据,而不考虑返回数据是什么。
2.什么时候用EXISTS操作符
(1)常用于相关子查询
(2)需求中往往有至少的关键词

示例:
SELECT NAME,initials ##initials表示首字母
FROM players p
WHERE EXISTS ( ##exists表示后边的select语句是否返回数据
SELECT 1 ##如果是一行数据返回一个1,多行数据返回多个1
FROM penalties
WHERE playerno = p.playerno );
语句示例:得到那些至少支付了一次罚款的球员的名字和首字母
语句分析:就是拿着外查询的结果去比较内查询的结果,如果两个结果相符,则保留结果,否则将结果摒弃

NOT EXISTS操作符
1.该操作符专门判断子查询的结果集是否不为空:如果为空则返回true,否则返回false,跟exists操作符相反

2.什么时候使用NOT EXISTS操作符
(1)常用于相关子查询
(2)需求中往往有”不是”关键字

示例:
SELECT NAME,initials
FROM players p
WHERE NOT EXISTS( ##如果返回数据是队长,不返回数据则是不是队长符合需求
SELECT 1
FROM teams
WHERE playerno = p.playerno );
语句释义:得到那些不是队长的球员的名字和首字母

总结:
子查询先执行,执行完毕之后,再执行外边的,从里到外的执行结构
单行单列比较的时候 = (子查询也得是单行单列)
单行多列比较的时候 = (子查询也得是单行多列)
过滤列(单列) in (当子查询是多行单列)
过滤列(多列) in (当子查询是多行多列)

猜你喜欢

转载自blog.csdn.net/qq_43028054/article/details/93760897