sql join 子查询_SQL基础丨子查询

06ad68e1485a4c9103a49ef4f97b19dc.png

关联子查询,非关联子查询

子查询虽然是一种嵌套查询的形式,不过依然可以一句子查询是否执行多次,从而将子查询划分为关联子查询和非关联子查询。

子查询从数据表中查询了数据结果,如果这个数据结果只执行一次,然后这个数据结果作为主查询条件进行执行,那么这样的子查询叫做非关联子查询。

如果子查询执行多次,即采用循环的方式,先从外部查询开始,每次都传入子查询进行查询,然后再将结果返回给外部,这种嵌套的执行方式就称为关联子查询。

以NBA球员数据库为例,文件中一共包括5张表,player表为球员,team为球队表,team_score为球队比赛表,player_score为球员比赛成绩表,height_grades为球员身高对应的等级表。

player表,37个球员

e1124a172bd09e238c9c21479c0520c9.png

team表,3支球队。

0ae655862e9728f970b773291702163b.png

team_score表,一共记录两场比赛

d335eaf27d8fd0cec0af25bff0d5e5d1.png

player_score表,记录了一场比赛中球员的表现,包含19个字段

03220fc0381a90a912f3a3388de2d551.png

注:数据表字段比较多的时候,为了防止混淆字段,最好的方式就是做个说明文档,用实例举例。

例:shoot_attempts是总出手次数(这里的总出手次数=二分球出手次数+三分球出手次数,不包含罚球的次数)。

示例

- 获取球员的最高身高,最高身高是多少

SQL: SELECT player_name, height FROM player WHERE height = (SELECT max(height) FROM player)

运行结果

035d26cfd768ed28e9db2f18f547b1a4.png

通过SELECT max(height) FROM player可以得到最高身高这个数值,结果为2.16,然后再通过player这个表,看谁具有这个身高,再进行输出,这样的子查询就是非关联子查询。

如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此没执行一次外部查询,子查询都要重新计算一次,这样的子查询就称关联子查询。

示例

- 想要查找每个球队中大于平均身高的球员有哪些,显示他们的姓名、身高以及所在球队ID

SELECT player_name, height, team_id FROM player AS a WHERE height > (SELECT avg(height) FROM player AS b WHERE a.team_id = b.team_id)

运行结果:(18条记录)

8db490370e908e5852f7b36d6e84e6f8.png

这里将player表复制成了表a和表b,每次计算的时候,需要将表a中的team_id传入从句,作为已知值。因为每次表a中的team_id可能是不同的,所以是关联子查询。如果是非关联子查询,那么从句计算的结果是固定的才可以。

EXISTS子查询

关联子查询通常会和EXISTS一起使用,EXISTS子查询用来判断条件是否满足,满足的话为True,不满足为False。

示例

- 查看出场过的球员有哪些,并显示他们的姓名、球员ID和球队ID(是否出场通过player_score)这张表中的球员出场表现来统计,如果球员在player_score中有过出场记录则代表他出场过)

SQL:SELECT player_id, team_id, player_name FROM player WHERE EXISTS (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)

运行结果(19条记录)

83658ac40d561a010dae06e80db0b6b1.png

NOT EXISTS是不存在的意思

SQL: SELECT player_id, team_id, player_name FROM player WHERE NOT EXISTS (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)

运行结果:(18条记录)

b32207b96040100acb182af180fba1fe.png

集合比较子查询

7650245cd35ff5e8090a5958564655a5.png

上面例子,采用IN子查询来进行操作

SELECT player_id, team_id, player_name FROM player WHERE player_id in (SELECT player_id FROM player_score WHERE player.player_id = player_score.player_id)

运行结果和EXISTS相同

IN和EXISTS的选择

抽象示例

SELECT * FROM A WHERE cc IN (SELECT cc FROM B)
SELECT * FROM A WHERE EXIST (SELECT cc FROM B WHERE B.cc=A.cc)

实际查询过程中,对cc列建立索引的情况下,还需要判断表A和表B的大小。在这个例子当中,表A指的是player表,表B指的是player_score表,如果表A表比表B大,那么IN查询的效率要比EXIST子查询效率高,因为这时B表中如果对cc列进行了索引,那么IN子查询的效率就会比较高。

如果表A比表B小,那么使用EXISTS子查询效率会更高。

使用ANY和ALL需要使用比较符

示例

- 比印第安那步行者(对应的team_id为1002)中任意一个球员身高高的球员信息,并且输出他们的球员表ID、球员姓名和球员身高。

SQL: SELECT player_id, player_name, height FROM player WHERE height > ANY (SELECT height FROM player WHERE team_id = 1002)

运行结果

53693a52345c5c9cd6aca424ea2d4f65.png

- 查询比印第安纳步行者中所有球员身高都高的球员的信息,并且输出球员ID、球员姓名和球员身高

SQL: SELECT player_id, player_name, height FROM player WHERE height > ALL (SELECT height FROM player WHERE team_id = 1002)

运行结果

19d4fdf359dfe7afbce18ab8232d6bc0.png

将子查询作为计算字段

示例

- 查询相同team_id在player表中所有球员的数量是多少

SQL: SELECT team_name, (SELECT count(*) FROM player WHERE player.team_id = team.team_id) AS player_num FROM team

运行结果:(3条记录)

4bf7083047b1744b480e096693521e05.png

总结

4702f1a3cc79ec2f3470deb8b8d063ac.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值