10 mysql高级查询:联合查询union,内连接inner join,外连接left join,子查询

1 联合查询:合并结果集-不推荐

概念

联合查询就是: 将多个查询的结果合并到一起(纵向合并):字段不变,多个查询的记录数合并(产生的结果是笛卡尔积)
等同于将一个表追加到另一个表,从而实现将两个表的查询组合到一起的效果,使用关键字 unionunion all

语法

select 语句
union [union 选项]
select 语句;


-- union选项
distinct:去掉完全重复的数据(默认)
all:保存所有的结果

在联合查询中,如果要使用 order by,那么对应的select 语句 必须使用括号括起来,同时必须结合limit使用
limit的数量:通常可以使用一个较大的值,大于对应的表的记录数

应用场景

1、 将同一张表中的不同结果(需要对应多条查询语句来实现),合并到一起展示数据

-- 获取男生成绩降序 女生的成绩升序的结果集
(SELECT * from student WHERE gender='男' ORDER BY score desc)
UNION
(SELECT * from student WHERE gender='女' ORDER BY score);

2、 常用--在数据量很大的时候,通常会进行分表操作,需要对每张表进行部分数据的统计,就需要使用联合查询将结果合并到一起展示

2 连接查询--推荐 内连接join

概念

连接查询:将多张表连接在一起进行查询:会导致字段列表和记录数都发生变化。

在关系型数据库设计的过程中,实体(表)和实体之间存在很多联系:一对一、多对一、多对多,通常在实际操作过程中,我们需要利用这层关系,来保证数据的完整性

2.1 内连接(inner join):on 匹配条件--推荐

内连接:inner join,从一张表中取出所有的记录去另外一张表中进行有条件的匹配,符合条件的数据保留

注意:

内连接必须要有匹配条件 on,否则么有任何意义
表1和表2之间,必须要有关联

原理

  • 1 从一张表取出一条记录,然后去另外一张表中进行匹配
  • 2 利用匹配条件进行匹配
    • 2.1 匹配到数据:保留此条数据,继续向下匹配
    • 2.2 没有匹配到数据:向下继续匹配,直到全表匹配完毕

语法

-- inner 可以省略
表1 [inner] join 表2 on 匹配条件;


-- 查询学生所在班级及其所在班级的名称
-- 因为表的设计通常会容易产生同名字段,为了保证数据的唯一性,可以使用 表名.字段名 来确保唯一性
-- 如果条件中使用的表名比较长,一般会使用表别名来替换

SELECT stu.name '姓名',c.name '班级' from student stu join class c on stu.class_id=c.id;

应用场景

内连接通常是在对数据有精确要求的地方使用:必须保证两表中都可以匹配到数据

2.2 外连接(outer join):on 匹配条件

外连接:一张表作为主表(主表中所有记录都保留),根据条件去连接另外一张表(从表),得到目标数据

外连接主要分为左外连接(left join)和右外连接(right join)

左连接:左侧的表是主表
右连接:右侧的表是主表

外连接中主表的数据记录一定会保留,连接后不会出现记录数小于主表记录数的情况(内连接会,因为内连接会把不符合条件的过滤掉)

原理

1、 确定连接主表:左连接:左侧的表是主表;右连接:右侧的表是主表

2、 拿主表的每一条记录去匹配从表的每一条记录

3、 匹配条件满足,保留记录;否则不保留记录

4、 如果主表记录在从表中一条记录都没有匹配成功,那么也要保留该记录,只不过从表对应的字段值都是NULL

语法

-- 左连接:
主表 left join 从表 on 条件

-- 右连接:
从表 left join 主表 on 条件

-- 左连接对应的主表数据在左边
-- 右连接对应的主表数据在右边


-- 班级信息表是主表,保留所有记录,学生信息表示从表,如果没有匹配到数据,从表对应的数值都是null
SELECT * from class c left join  student stu  on stu.class_id=c.id;

2.3 连接查询-using关键字--少用

主要是在连接查询中,用来替换 on 关键字进行条件匹配的

使用using的时候,对应2张表中连接的字段必须是同名的

原理

1、 在连接查询的时候,使用on的地方使用 using 替换

2、 使用using的前提是:两张对应关联的表连接的字段必须是同名的

3、 使用using关键字后,对应的同名字段只会保留一个

语法

表1 [inner,left,roght] join 表2 using(同名字段)

2.4 交叉连接(cross join)-不推荐

交叉连接:将一张表的数据与另一张表的数据进行彼此交叉

交叉连接产生的结果是笛卡尔积,会产生较大的结果集,没有实际应用

原理

1、 从第一张表依次取出每一条记录
2、 取出每一条记录后,与另外一个表的全部记录逐个匹配
3、没有任何匹配条件,所有的结果都会进行保留
4、记录数=第一张表的记录数 * 第二张表的记录数,字段数=第一张表的字段数+第二张表的字段数

语法

表1 cross join 表2;


-- 连接查询:学生信息表 和 班级信息表
SELECT * from student CROSS JOIN (SELECT * from class) as class;

image

子查询

子查询是sql查询语言中嵌套查询下层的程序模块。就是当一个查询是另外一个查询的条件时,这个查询就是子查询

子查询:在一条select查询语句中,嵌入了另外一条select语句,那么被嵌入的这个select语句是子查询语句

主查询

主查询:主要的查询对象,第一条select语句,确定用户所获取的数据模板(数据源)

与子查询的关系:

  • 子查询是嵌入到主查询中的
  • 子查询主要是辅助主查询的
  • 子查询也是可以独立存在的,因为子查询是一条完整的select语句

子查询的分类

按照功能分类

  1. 标量子查询:子查询返回的结果是一个数据(一行一列)

  2. 列子查询:子查询返回的结果是一列数据(一列多行,同一个字段不同的值)

  3. 行子查询:子查询返回的结果是一行数据(一行多列,就是完整的一条记录)

  4. 表子查询:子查询返回的结果是多行多列表

  5. exists子查询:返回的结果是1或0(类似布尔操作)

按照位置分类

where子查询(较多):子查询出现的位置在where条件中

from子查询:子查询出现的位置在from后面,作为数据源使用

标量子查询--where子查询

标量子查询:子查询得到的结果是一个数据(一行一列)

-- 语法:
-- 通常使用 =  或 <> 关键字,获取一个数据
-- 子查询select 字段名 from 数据源 where 条件 得到的结果只有一个值
select * from 数据源 where 条件 =或者<> (select 字段名 from 数据源 where 条件);

-- 查询 张三所在班级的名称
-- 标量子查询语句:SELECT class_id from student WHERE name='张三'; 返回一个数据
SELECT name from class WHERE id=(SELECT class_id from student WHERE name='张三');

列子查询--where子查询

列子查询:子查询返回的结果是一列数据(一列多行,同一个字段不同的值)

-- 语法
-- 通常使用 in 关键字
主查询 where in(列子查询)



SELECT * from student WHERE class_id in(SELECT id from class);

行子查询--where子查询

行子查询:子查询返回的结果是一行数据(一行多列,就是完整的一条记录)

行元素:字段元素是指一个字段对应的值。行元素就是对应多个字段合起来作为一个元素参与运算。

-- 语法
主查询 where 条件(构造一个行元素)=(行子查询)

-- 获取班级中,年龄最小且分数最高的学生
-- 1 查询 年龄最小的
-- 2 查询 分数最高的
-- 3 查询 龄最小且分数最高的学生

SELECT * from student WHERE(score,age)=(SELECT max(score),min(age) from student);

--等价与下面的:
SELECT * from student WHERE age=(SELECT min(age) from student) and score=(SELECT max(score) from student);
-- 行子查询 结果
SELECT max(score),min(age) from student;

表子查询--from子查询

表子查询:子查询返回的结果是多行多列

表子查询与行子查询类似,只是行子查询会产生行元素,表子查询没有行元素

行子查询主要用于where条件判断:where子查询
表子查询主要用于from数据源:from子查询

-- 语法:
select 字段列表 from (表子查询) as 别名;

-- 获取每个班级中分数最高的学生
-- 1  获取每班成绩最高的分数
SELECT class_id,max(score) as score from student GROUP BY class_id;
-- 2 针对1种结果 进行合并查询

-- 查询每个班级的最高成绩学生信息
SELECT *
FROM student s1
JOIN (
    SELECT class_id, MAX(score) as score
    FROM student
    GROUP BY class_id
) s2 ON s1.class_id = s2.class_id AND s1.score = s2.score
ORDER BY s1.class_id, s1.score DESC;

exists 子查询

exists 子查询:查询返回的结果只有1或0

-- 语法:
-- exists根据查询得到的结果进行判断,如果结果存在,返回1;否则返回0
where exists(查询语句);

子查询中的特殊关键字

in--常用

主查询 where 条件 in(列子查询);

any

-- 任意一个,此时等价与 in
=any(列子查询):条件在查询结果中任意一个满足即可

<>any(列子查询):条件在查询结果中不等于任意一个

some

some与any一样

all

posted @ 2024-07-11 18:10  songxia777  阅读(118)  评论(0编辑  收藏  举报