准备测试数据

drop table if exists stu;
create table stu(
id int auto_increment primary key,
name varchar(20),
age int
);
insert into stu values (null, 'BNTang', 23);
insert into stu values (null, '李四', 18);
drop table if exists grade;
create table grade(
id int auto_increment primary key,
km varchar(20),
score double,
uid int
);
insert into grade values (null, '语文', 100, 2);
alter table grade add foreign key(uid) references stu(id);
insert into grade values (null, '语文', 100, 2);
insert into grade values (null, '语文', 90, 1);
create table person(
id int primary key,
name varchar(20)
);
insert into person values (1, 'BNTang');
insert into person values (2, 'JonathanTang');

多表查询

  • 多表查询只需要在单表查询基础上增加一张表即可
  • 语法:select * from 表名1, 表名2;
select * from stu, grade;

????注意点

  • 默认情况下多表查询的结果是笛卡尔集

union

  • 在纵向上将多张表的结果结合起来返回给我们
  • 语法:select * from 表名1 union select * from 表名2;
select id, name from stu union select id, score from grade;

????注意点

  • 使用​​union​​进行多表查询, 返回的结果集的表头的名称是第一张表的名称
  • 使用​​union​​进行多表查询, 必须保证多张表查询的字段个数一致
select id, name from stu union select id, score, uid from grade;# The used SELECT statements have a different number of columns
  • 使用​​union​​进行多表查询, 默认情况下会自动去重
select id, `name` from stu union select id, name from person;
  • 使用​​union​​​进行多表查询, 如果不想自动去重, 那么可以在union后面加上​​all​
select id, `name` from stu union all select id, `name` from person;

表的连接查询

  • 将多张表中关联的字段连接在一起查询我们称之为​​表的连接查询​
  • 大白话:查询多张表中满足条件的数据

内连接

通过使用​​inner join​​关键字进行内连接查询

语法:select * from 表名1 inner join 表名2 on 条件;

select * from stu, grade where stu.id = grade.uid;
select * from stu inner join grade on stu.id = grade.uid;

????注意点

  • 在进行多表查询的时候, 如果想查询指定的字段, 那么必须在字段名称前面加上表名才行
select stu.id, stu.`name`, grade.score from stu inner join grade on stu.id = grade.uid;
  • 在内连接中只会返回满足条件的数据

外连接

又分左外连接和右外连接,首先来看看左外连接,通过使用​​left join​​关键字实现

  • 在左外连接中, 左边的表是不看条件的, 无论条件是否满足, 都会返回左边表中所有的数据
  • 在左外连接中, 只有右边的表会看条件, 对于右边的表而言, 只有满足条件才会返回对应的数据
select stu.id, stu.`name`, grade.score from stu left join grade on stu.id = grade.uid;
  • 在以上的查询语句中stu表在左边, grade表在右边
  • 所以stu表不看条件, 只有grade表看条件

右外连接,通过使用​​right join​​关键字实现

  • 在右外连接中, 右边的表是不看条件的, 无论条件是否满足, 都会返回右边表中所有的数据
  • 在右外连接中, 只有左边的表会看条件, 对于左边的表而言, 只有满足条件才会返回对应的数据
select stu.id, stu.`name`, grade.score from stu right join grade on stu.id = grade.uid;
  • 在以上的查询语句中stu表在左边, grade表在右边
  • 所以grade表不看条件, 只有stu表看条件

交叉连接

通过使用​​cross join​​关键字进行交叉连接查询

  • 如果没有指定条件, 那么返回的数据中会有笛卡尔集
select stu.id, stu.`name`, grade.score from stu cross join grade;
  • 如果指定了条件, 那么就等价于内连接
select stu.id, stu.`name`, grade.score from stu cross join grade on stu.id = grade.uid;

全连接

full join(MySQL不支持全连接)

自然连接

通过使用​​natural​​关键字进行自然连接查询

  • 自然连接是用来简化​​内连接和外连接​​的
  • 如果多张表需要判断的条件字段名称一致, 那么不用编写条件, 自然连接会自动判断

????自然内连接

  • 内连接:select * from 表名1 inner join 表名2 on 条件;
select * from stu inner join grade on stu.id = grade.uid;
  • 自然内连接:select * from 表名1 natural join 表名2;
select * from stu natural join grade;

????自然外连接

  • 自然左外连接
select * from stu natural left join grade;
  • 自然右外连接
select * from stu natural right join grade;

????注意点

  • 如果没有指定条件, 也没有同名的字段, 那么就会返回笛卡尔集
  • 在自然连接中, 返回的结果集会自动优化, 会自动去除重复的判断字段

using

  • 如果多张表需要判断的条件字段名称一致, 那么除了可以使用自然连接来简化以外
  • 还可以使用​​using​​关键字来简化

????内连接

select * from stu inner join grade on stu.id = grade.uid;
select * from stu inner join grade using(id);

????外连接

  • 左外连接
select * from stu left join grade on stu.id = grade.uid;
select * from stu left join grade using(id);
  • 右外连接
select * from stu right join grade on stu.id = grade.uid;
select * from stu right join grade using(id);

子查询

  • 将一个查询语句查询的结果作为另一个查询语句的条件来使用
  • 将一个查询语句查询的结果作为另一个查询语句的表来使用

????将一个查询语句查询的结果作为另一个查询的条件来使用

  • 标准子查询(返回的结果只有一个)
select uid from grade where score = 100;
select `name` from stu where id = 3;
select name from stu where id = (select uid from grade where score = 90);
  • 非标准子查询(返回的结果有多个)
select uid from grade where score >= 60;
select `name` from stu where id = 3 OR id = 1;
select `name` from stu where id in(3, 1);
select name from stu where id in(select uid from grade where score >= 60);

????将一个查询语句查询的结果作为另一个查询的表来使用

select `km`, `score` from grade where score >= 60;
select `km`, score from (select `km`, `score` from grade where score >= 60) as t;

????注意点

  • 如果要将一个查询语句查询的结果作为另一个查询的表来使用, 那么必须给子查询起一个别名