0


「MySQL」查询方式(5k字长文!超详细!)

🎇个人主页:Ice_Sugar_7
🎇所属专栏:数据库
🎇欢迎点赞收藏加关注哦!

查询方式

🍉聚合查询

前面我们讲查询时带表达式,比如成绩表中有语文、数学、英语三个科目,我们要查询总分,就要用到:

select chinese + math + english from...

**这种查询方式实际上是在进行

列和列

之间的运算
而聚合查询,则是进行“行与行”之间的运算,不过这里行之间的运算有一定的限制——只能通过

聚合函数

来进行操作,这就需要用到SQL提供的一些库函数了**。聚合查询不像表达式查询那样随便写表达式就可以了

下面我们来看一下常用的聚合函数:
在这里插入图片描述

🍌count

现在有一个学生表:
在这里插入图片描述

selectcount(*)from students;

这行代码得到结果为4,它就相当于先执行:

select*from students;

然后再使用 count 来计算结果的行数
**大多数情况下,

count(*)

count(列名)

没什么区别,在特定情况下才会有差异**

比如,往上面的学生表中插入一个姓名为

NULL

的记录:在这里插入图片描述

我们用 select count(*) 和 select count(name) 分别查询,得到的结果不一样
在这里插入图片描述

由此我们可以得出一个结论:**查询指定列时,如果查询结果带有

null值

,那么此时

null值

的记录不会计入计数;而如果使用

count(*)

,则会计入计数**

🍌sum

现在有如下的成绩表:
在这里插入图片描述

通过sum可以得到总的语文成绩

selectsum(chinese)from grade;

sum 可以把某一列的值全部放在一起相加,在这个过程中,会把

null

给忽略掉,也就是说此时

null

相当于 0

除了数字求和,如果将名字进行求和会得到什么?

selectsum(name)from grade;

在这里插入图片描述
可以看到只报警告而没有报错

**在SQL中,如果把字符串当作数字来进行算术运算,就会尝试

把字符串转成数字

。但是上面这些名字是无法转成数字的,所以报警告**

而如果我们插入一个数字字符作为名字的记录,那就可以转成数字了(不过现实中肯定没人这么起名的hhh)
在这里插入图片描述

这次就可以得到结果了:

在这里插入图片描述

至此,我们已经介绍了 sum 的用法,剩下的 avg、min、max 的用法和 sum 基本类似,所以也就不再赘述了,接下来就直接用了

现在我们要查询成绩表中,数学分数最低的同学:
在这里插入图片描述

但是我们查询出来的姓名和成绩对不上!

正常来说,一行数据每个列都是对应的(比如张一学号为1,数学考了80),这些列共同构成了一条记录。但是,如果查询中包含聚合函数和非聚合的列,那么结果中的列就不是对应的(相当于各打各的)

**这是在因为使用聚合函数的时候,列和列之间的顺序已经被“打散”了。所以大部分情况下,聚合的列和非聚合的列不能一起使用。当然,有一种情况例外,那就是

group by

**

在此之前,先回到上面的例子,要找出数学成绩最低的同学,我们可以将 order by 和 limit 配合使用:

在这里插入图片描述
(顺便提一句,order by 默认是按升序排序的)

🍌group by

**刚才的聚合是把整个表所有行都聚合在一起,不过也可以先把所有行分成若干组,然后分别对每个组进行聚合,需要用到

group by

**

groupby 列名

**它的效果就是把指定的列,其中

值相同的记录

划分到一组,针对这些组就可以分别进行聚合查询了**

举个例子,比如现在要按照岗位,对职工表中员工的工资进行查询以及统计,就可以使用group by 了

在这里插入图片描述

在 select 列名的时候,列名是可以写role的,因为我们是按 role 来分组的
但是注意不能写 id 或者 name,因为这样写的话你会发现一个记录它的列是对不上的,如下图:

在这里插入图片描述
这就类似刚才上面查询数学成绩的同学这个例子

总结一下就是:非聚合的列不能和聚合的列或者 group by 的列一起使用

**对于分组查询,它也是可以对查询结果进行条件筛选的,分组后的条件,用

having

来表示,它的用法和where是一样的,只不过 where 是用于分组之前的条件**

下面应用一下 having
例1:要统计平均薪资高于10000的岗位

select role,avg(salary)from emp groupby role havingavg(salary)>10000;

在这里插入图片描述

例2:要统计每个岗位的平均薪资,不包括李四,同时除去平均薪资低于13000的情况

统计平均薪资的时候不包括李四,这是在分组之前进行的,要用where;而筛选出平均薪资高于13000的情况,这是在分组后进行的,要用 having

select role,avg(salary)from emp where name !='李四'groupby role havingavg(salary)>13000;

在这里插入图片描述


🍉联合/多表查询(面试常考)

前面的查询都是针对一张表的,而多表查询自然是针对多张表的,它比单表查询要复杂一些

**在正式讲多表查询之前,需要先引入一个概念——

笛卡尔积

**
**所谓笛卡尔积,其实就是简单的

排列组合

**
笛卡尔积的列数就是之前两个表的列数之和;而行数则是之前两个表的行数之积

如果表更多,比如有三张表A、B、C,那么就是先计算 A 和 B 的笛卡尔积,算出来的结果再和 C 计算笛卡尔积
(注意:将两个很大的表进行笛卡尔积是一个危险操作,因为会产生大量的运算和 IO,可能把数据库搞挂了)

🍌两个表的联合查询

**联合查询的

核心操作

就是进行笛卡尔积,比如使用两个表进行联合查询,就是先把这两个表计算笛卡尔积**
比如同时查询学生表和成绩表:

select*from students,grade;

得到下面的结果:
在这里插入图片描述

细看一下我们会发现,有一些记录是无效的,就学生表中的 id 对不上 成绩表中的 id

所以我们再指定一些条件,来得到预期的查询结果
我们要让两个表中 id 一样的记录才能配对

select*from students,grade where students.id = grade.id;
students.id = grade.id

这个把两个表连接起来的条件,就叫作

连接条件

在这里插入图片描述

不过也不是随便拿来两个表就能进行笛卡尔积,一定要确保这两个表有一定的

关联关系

,即至少有一个列是有关联的

总结:多表查询的一般步骤
①笛卡尔积
②连接条件
③根据需求指定其他条件
④针对列进行精简 or 使用聚合函数

除了上面的写法之外,联合查询还有一种写法,也能实现一样的效果:

select*from 表1join 表2on 连接条件;

所以上面的例子,我们也可以写为

select*from students join grade on students.id = grade.id;

可以得到一样的结果

在这里插入图片描述

再来看一个例子
现有学生表和课程表这两个表
在这里插入图片描述

现在要求每位同学所有课程的总分

思路:按照上面的步骤,先笛卡尔积,然后指定连接条件
我们要查看的列就是姓名和总分这两列

select students.name,sum(course.score)from students,course where students.id = course.student_id;

然后根据需求指定其他条件:因为我们是要统计每一位学生的成绩,所以就要按学生名字进行分组,这就要用到 group by

select students.name,sum(course.score)from students,course where students.id = course.student_id groupby students.name;

接下来就是对列进行精简或者使用聚合函数,因为我们的目的就是求和,所以一开始就已经使用聚合函数 sum 了,这一步就不用再考虑了

🍌多个表的联合查询

上面举的例子的中有学生表和课程表这两个表,现在要再加入另一个表——课程学分表,它包括课程名字和课程学分
在这里插入图片描述

那如何把它和前面两个表连接起来呢?
我们可以发现,课程学分表和学生表之间其实没有联系,因为它们没有相关联的列;反之,它和课程表就很有联系——都有“课程名字”这一列
所以先把它们俩连起来

select*from course,credit where course.course_name = credit.course_name;

在这里插入图片描述
接下来再把这个表和学生表连起来
只需在原来的基础上,再查询一下学生表,并加上连接条件(即学生表的 id 和课程表的学生 id 相等),现在就有两个连接条件了,用 and 把两条件结合起来

select*from students,course,credit where students.id = course.student_id and course.course_name = credit.course
_name;

在这里插入图片描述
不过查询结果的列数太多了,我们需要精简一下,三个表分别查询指定列就 ok 了

select students.name,students.id,course.course_name,course.score,credit.credit from students,course,credit where
students.id = course.student_id and course.course_name = credit.course_name;

这条SQL语句看起来很长,但是我们拆分成一步步来写,其实也就没那么复杂了

在这里插入图片描述

上面的SQL语句也可以使用 join on 来改写:

select students.name,students.id,course.course_name,course.score,credit.credit from students join course on stude
nts.id = course.student_id join credit on course.course_name = credit.course_name;

另外,在多表查询中,前面涉及到的去重、排序、limit 等操作也是同样适用的,具体就不演示了


🍌外连接

**刚才上面那些写法,叫作

内连接

,而

外连接

也是多表查询的一种体现形式
在大多数情况下,内连接和外连接的查询结果没什么区别,只有在一些特殊情况下,查询结果才会存在差异**

那么“大多数情况”是什么样的情况呢?举个例子:

在这里插入图片描述

在上面的学生表和成绩表中,这两个表的数据是一一对应的,即学生表中的任何一个记录都能在分数表中体现出来;反过来,分数表中的每个记录,也能在学生表中体现出来,那此时外连接和内连接的结果就是一样的

**前面我们说可以使用 join on 进行联合查询,其实那里的 join 前面省略了

inner

,它表示内连接,一般 inner 是不用写的**

**而外连接分为

左外连接

右外连接

,需要在 join 前面分别加上

left

right

**

举例,现有两张表
在这里插入图片描述

注意,课程表中没有赵六的信息
分别对学生表和课程表进行左、右外连接,得到如下结果:

在这里插入图片描述

可以发现左外连接的结果有赵六这条记录,右表中的列全为 NULL;而右外连接没有这条记录
结论如下:

①左外连接就是以左表为主,保证左侧的表(join 左边的表)每个记录都体现在最终结果里,如果这个记录在右表中没有匹配,就把对应的列填成 NULL
②同理,右外连接就是以右表为主,保证右表中每个记录都存在,如果对应的数据在左表中没有,则会填成 NULL


🍉子查询

其实就是套娃,把多个简单 sql 合并为一个复杂的 sql
注意:实际开发中不建议这样写,因为当有多个 sql 语句时,合并后就是一坨…
我们不写 ≠ 别人不写,为了看懂别人写的子查询 sql,我们还是有必要学习一下

举一个简单的例子,比如现在要从下面这个表中找出张一的同班同学的名字

在这里插入图片描述
照正常的思路,那就是先找出张一的班级:
在这里插入图片描述
然后再找出1班中名字不是张一的同学:
在这里插入图片描述

可以看到,在这个过程中,我们进行两次查询,先得到班级信息,然后由此进行第二次查询得到同学姓名
使用子查询的话,那就是将上面这两步合并起来:

select name from students where name !='张一'and classid =(select classid from students where name ='张一');

🍉合并查询

**这个查询很好理解,就是把两个查询结果的结果集,合并成一个集合,这个过程我们使用

union

关键字来完成**

语法:

select1unionselect2

注意:合并查询要求两个 select 查询的结果集的列数和类型要匹配,最终的列名就是第一个 select 的列名

**合并查询看起来和 or 差不多,但是 or 只能在一个表中进行查询,而 union 左右两侧的 sql 可以是查询两个不同的表,并且还会自动对查询结果进行

去重

(如果使用

union all

的话,则不会去重)**

下面还是举些例子运用 union:

在这里插入图片描述

select*from students where name ='张三'unionselect*from students where id =1;

在这里插入图片描述

select*from students where name ='张三'unionselect*from students where id =2;

在这里插入图片描述

标签: mysql android 数据库

本文转载自: https://blog.csdn.net/Ice_Sugar_7/article/details/137019459
版权归原作者 Ice_Sugar_7 所有, 如有侵权,请联系我们删除。

“「MySQL」查询方式(5k字长文!超详细!)”的评论:

还没有评论