关联子查询和非关联子查询
子查询从数据表中查询了数据结果,如果这个数据结果只执行一次,然后这个数据结果作为主查询的条件进行执行,那么这样的子查询叫做非关联子查询。
如果子查询需要执行多次,即采用循环的方式,先从外部查询开始,每次都传入子查询进行查询,然后再将结果反馈给外部,这种嵌套的执行方式就称为关联子查询。
eg:
非关联子查询:
SELECT player_name, height FROM player WHERE height = (SELECT max(height) FROM player)
子查询所需要的数据不需要从外部查询获得。
关联子查询:
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)
子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此每执行一次外部查询,子查询都要重新计算一次。
EXISTS子查询
关联子查询通常也会和 EXISTS 一起来使用,EXISTS 子查询用来判断条件是否满足,满足的话为 True,不满足为 False。
eg:
查询出场过的球员都有哪些,并且显示他们的姓名、球员 ID 和球队 ID。在这个统计中,是否出场是通过 player_score 这张表中的球员出场表现来统计的,如果某个球员在 player_score 中有出场记录则代表他出场过。
SELECT play_id,team_id,player_name FROM player WHERE EXISTS (SELECT player_id FROM play_score WHERE player.player_id = player_score.player_id);
NOT EXISTS 就是不存在的意思,我们也可以通过 NOT EXISTS 查询不存在于 player_score 表中的球员信息.
集合比较子查询
集合比较子查询的作用是与另一个查询结果集进行比较。
操作符:
IN 判断是否在集合中
ANY 需要与比较操作符一起使用,与子查询返回的任何值做比较 (集合里的最小值)
ALL 需要与比较操作符一起使用,与子查询返回的任何值做比较 (集合里的最大值)
SOME 功能同ANY
eg:
查询出场过的球员都有哪些:
SELECT player_id, team_id, player_name FROM player WHERE player_id IN(SELECT player_id FROM play_score WHERE player.player_id = player_score.player_id);
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)
IN表是外边和内表进行hash连接,是先执行子查询。
EXISTS是对外表进行循环,然后在内表进行查询。
in 判断是否在集合中 exists 判断是否存在,两者的差异性导致调用顺序不同。
如果表 A 比表 B 大,那么 IN 子查询的效率要比 EXIST 子查询效率高;如果表 A 比表 B 小,那么使用 EXISTS 子查询效率会更高。
ANY 和 ALL
eg :
查询球员表中,比印第安纳步行者(对应的 team_id 为 1002)中任意一个球员身高高的球员信息,并且输出他们的球员 ID、球员姓名和球员身高。
SELECT player_id, player_name, height FROM player WHERE height > ANY(SELECT height FROM player WHERE team_id = 1002);
查询比印第安纳步行者(对应的 team_id 为 1002)中所有球员身高都高的球员的信息:
SELECT play_id,player_name, height FROM player WHERE height < ALL (SELECT height FROM player WHERE team_id = 1002);
将子查询作为计算字段
子查询也可以作为主查询的计算字段:
eg:查询每个球队的球员数:
SELECT team_name, (SELECT count(*) FROM player WHERE player.team_id = team.team_id) AS player_num FROM team;