MySql的复杂查询

  • 一、连接查询
  • 1.1、CROSS JOIN(交叉连接)
  • 1.2、等值连接
  • 1.2.1、NATURAL JOIN(自然连接)
  • 1.2.2、USING 连接
  • 1.2.3、ON 连接
  • 1.3、非等值连接
  • 1.4、外链接
  • 1.4.1、LEFT OUTER JOIN (左外连接)
  • 1.4.2、RIGHT OUTER JOIN(右外连接)
  • 1.4.2、FULL OUTER JOIN(全外连接)
  • 1.5、自连接
  • 二、联合查询
  • 三、子查询
  • 3.1、EXISTS 子查询
  • 3.2、集合比较子查询
  • 3.3、子查询作为计算字段


一、连接查询

1.1、CROSS JOIN(交叉连接)

交叉连接也叫笛卡尔乘积。wikipedia 对笛卡尔乘积的定义如下:
    在数学中,两个集合 X 和 Y 的笛卡儿积(英语:Cartesian product),又称直积,在集合论中表示为 X x Y ,是所有可能的有序对组成的集合,其中有序对的第一个对象是 X 的成员,第二个对象是 Y 的成员。

SELECT * FROM player;                     # 见图一
 SELECT * FROM team;                       # 见图二
 SELECT * FROM player CROSS JOIN team;     # 见图三

MySQL复杂查询 mysql数据库复杂查询educoder_MySQL复杂查询


MySQL复杂查询 mysql数据库复杂查询educoder_数据库_02


MySQL复杂查询 mysql数据库复杂查询educoder_MySQL复杂查询_03

1.2、等值连接

等值连接就是对多张表中相同的字段进行等值判断。

1.2.1、NATURAL JOIN(自然连接)

会自动帮你查询两张连接表中所有相同的字段(比如两张表中相同的数据项) ,然后进行等值连接。

SELECT * FROM player NATURAL JOIN team;

MySQL复杂查询 mysql数据库复杂查询educoder_子查询_04

1.2.2、USING 连接

当然我们还可以用 USING 来指定用哪些同名字段进行等值连接。

SELECT * FROM player JOIN team USING(team_id);

MySQL复杂查询 mysql数据库复杂查询educoder_MySQL复杂查询_05

1.2.3、ON 连接

ON 表示我们想要连接的条件,我们也可以用 ON 来实现等值连接。

SELECT player_id, player.team_id, player_name, height, team_name 
 FROM player JOIN team ON player.team_id = team.team_id;

MySQL复杂查询 mysql数据库复杂查询educoder_子查询_06

1.3、非等值连接

连接两张表的条件如果是相等判断,那就是等值连接,否则就是非等值连接。

-- 我们想查询每个球员的身高级别。
 SELECT player_name,height,height_level
 from player JOIN height_grades
 on height BETWEEN height_lowest AND height_highest;

MySQL复杂查询 mysql数据库复杂查询educoder_mysql_07

1.4、外链接

外连接除了查询满足条件的记录以外,还可以查询某一方不满足条件的记录。两张表做外连接,会有一张表是主表,另一张表是从表。

1.4.1、LEFT OUTER JOIN (左外连接)

左外连接,就是左边的表是主表,需要显示左边表的全部行。右边表是从表,只显示满足条件的行。

-- girls 左连接是主表,需要显示左边表的全部行。右边表是从表,只显示满足条件的行。
 select girls.gid, gname, bname
 from girls left join boys
 on girls.bid = boys.bid;

1.4.2、RIGHT OUTER JOIN(右外连接)

右外连接,就是右边的表是主表,需要显示右边表的全部行。左边表是从表,只显示满足条件的行。

-- girls 右连接是主表,需要显示右边表的全部行。左边表是从表,只显示满足条件的行。
 select boys.bid, bname, gname
 from girls right join boys
 on girls.bid = boys.bid;

1.4.2、FULL OUTER JOIN(全外连接)

两张表都是主表,都需要显示全部行。但是MySQL不支持全外连接。

1.5、自连接

对同一张表进行连接查询,这样的连接我们称之为自连接。

-- 查看比布雷克-格里芬高的球员姓名及身高
 SELECT b.player_name, b.height 
 FROM player as a JOIN player as b 
 ON a.player_name = '布雷克-格里芬' and a.height < b.height;

二、联合查询

我们可以用 UNION 关键字,将多个结果集合并成一个结果集,这样的查询我们叫联合查询。例如:要查询的结果来自多个表,且多个表没有直接的连接关系,但查询的信息一致时。
注意事项: a. 列数一致
                  b. 对应的数据最好一致
                  c. UNION会去重, UNION ALL不会去重

-- 联合查询 union, union all 
  use friend;
  insert into boys values (5, "ET", null);
  insert into girls values (5, "ET", null);
  
  # 查询男生和女生的基本信息
  select * from boys
  union all select * from girls;     #会将所有查询结果显示出来不会进行去重

三、子查询

子查询其实就是嵌套在查询中的查询。这样做的好处是:我们可以进行更加复杂的查询,更容易理解查询的过程。很多情况下,我们无法直接从数据表中得到我们想要的结果。往往需要先进行一次查询,然后在这次查询的基础上,再次进行查询。

子查询可以分为关联子查询和非关联子查询。
-- 如果子查询只执行一次,然后子查询的结果集会作为外部查询的条件进行判断,那么这样的子查询叫做非关联子查询。
# 比如:我们想要查询哪个球员的身高最高,最高身高是多少?
# 1) 查询最高身高是多少?
  select max(height) from player;
# 2) 查询身高等于最高身高的球员信息。
  select * from player where height = (select max(height) from 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);

3.1、EXISTS 子查询

关联子查询可能会搭配 EXISTS 关键字一起使用。EXISTS 用来判断子查询的结果集是否为空集。
    如果不为空集返回 True ,如果为空集返回 False 。

-- 练习1:查询出过场的球员都有哪些,并显示他们的球员ID,球员姓名,球队ID。
 select player_id, player_name, team_id
 from player
 where exists (
   select player_id from player_score where player_score.player_id = player.player_id
 );
 
 -- 练习2::查询没出过场的球员都有哪些,并显示他们的球员ID,球员姓名,球队ID。
 select player_id, player_name, team_id
 from player
 where not exists (
  select player_id from player_score where player_score.player_id = player.player_id
 );

3.2、集合比较子查询

关键字

含义

IN

判断是否在子查询的结果集中

SOME (ANY)

需要与比较操作符一起使用,与子查询结果集中的某个值进行比较

ALL

需要与比较操作符一起使用,与子查询结果集中的所有值进行比较

SOME 和 ALL都需要和比较操作符一起使用,这些比较操作符包括: > , = , < , >= , <= , 和 <> 。

in -- :查询出过场的球员都有哪些,并显示他们的球员ID,球员姓名,球队ID
 select player_id, player_name, team_id
 from player
 where player_id in (select distinct player_id from player_score);



 some -- 比印第安纳步行者 (team_id=1002) 中所有球员身高都高的球员有哪些,显示它们的球员ID,球员姓名和球员身高(相当于大于最小值)。
 select player_id, player_name, height
 from player
 where height > some(select height from player where team_id = 1002);

 select * from player 
 where height > some(select height from player where team_id = 1002) and team_id <> 1002;

 select * from player 
 where height > (select min(height) from player as a where a.team_id = 1002)and team_id <> 1002;



all-- 想查询比印第安纳步行者 (team_id=1002) 中所有球员身高都高的球员有哪些,显示他们的球员ID,球员姓名和球员身高(大于最大值)。
 select player_id, player_name, height
 from player
 where height > all(select height from player where team_id = 1002);

 select * from player
 where height > all(select height from player where team_id = 1002);

 select * from player
 where height > (select max(height) from player where team_id = 1002);

最后,再强调下 SOME 和 ALL 必须要与一个比较操作符一起使用,不然起不到集合比较的作用。

3.3、子查询作为计算字段

子查询可以作为计算字段存在。我们通常会给这个计算字段起个别名,因为子查询实在
太长,别名更容易理解。

 -- 查询每个球队的名称,和它们的球员数。
 select team_name, 
 (select count(*) from player where player.team_id = team.team_id) AS player_num 
 from team;