【MySQL】表的增删改查

前言

前面我们对表结构做了介绍,本期我们对表的内容操作机增删改查进行介绍!

目录

前言

[一、insert 插入](#一、insert 插入)

[1.1 单行数据 + 全列插入](#1.1 单行数据 + 全列插入)

[1.2 多行数据 + 指定列插入](#1.2 多行数据 + 指定列插入)

[1.3 插入否则更新](#1.3 插入否则更新)

[1.4 插入否则替换](#1.4 插入否则替换)

[二、select 查询](#二、select 查询)

[2.1 select 列](#2.1 select 列)

[2.1.1 全列查询](#2.1.1 全列查询)

[2.1.2 指定列查询](#2.1.2 指定列查询)

[2.1.3 查询字段为表达式](#2.1.3 查询字段为表达式)

[2.1.4 为查询的结果指定别名](#2.1.4 为查询的结果指定别名)

[2.1.5 结果去重](#2.1.5 结果去重)

[2.2.1 运算符介绍](#2.2.1 运算符介绍)

[2.2.2 使用案例](#2.2.2 使用案例)

[2.2.3 order by 结果排序](#2.2.3 order by 结果排序)

[2.2.4 limit 分页查询](#2.2.4 limit 分页查询)

[三、Update 更新](#三、Update 更新)

[3.1 使用案例](#3.1 使用案例)

[四、Delect 删除](#四、Delect 删除)

[4.1 删除数据](#4.1 删除数据)

[4.1.1 删除指定的数据](#4.1.1 删除指定的数据)

[4.1.2 删除整张表](#4.1.2 删除整张表)

[4.2 截断表](#4.2 截断表)

五、插入查询结果

六、聚合函数

[6.1 什么是聚合函数](#6.1 什么是聚合函数)

[6.2 使用案例](#6.2 使用案例)

[七、group by 子句分组](#七、group by 子句分组)

[7.1 语法格式](#7.1 语法格式)

[7.2 使用案例](#7.2 使用案例)

[7.3 having 和 where 的区别?](#7.3 having 和 where 的区别?)

[7.4 分组的理解](#7.4 分组的理解)

[7.4 理解MySQL一切皆表](#7.4 理解MySQL一切皆表)


一、insert 插入

• 语法格式

sql 复制代码
INSERT [INTO] table_name [(列属性字段1)(,列属性字段2)...] VALUES(value_list)[, (value_list)]...;

• 准备工作

为了方便演示后续的操作,我们先来创建一张学生表。

表中字段有:id主键自增、学号sn唯一键且不为空、姓名name不为空、以及唯一键qq。

sql 复制代码
CREATE TABLE students (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    sn INT NOT NULL UNIQUE COMMENT '学号',
    name VARCHAR(20) NOT NULL,
    qq VARCHAR(20) UNIQUE
);

1.1 单行数据 + 全列插入

sql 复制代码
INSERT [INTO] table_name [(列属性字段1)(,列属性字段2)...] VALUES(value_list);

• 向表中插入一行数据,插入时需要和指定列字段属性(默认列属性字段)的顺序一致。

• 列属性字段属性列表在全列插入时可以省略。

• insert 操作时 into 可以省略

向表中插入一行数据,插入时需要和指定列字段属性(默认列属性字段)的顺序一致。

列属性字段属性列表在全列插入时可以省略。

insert 操作时 into 可以省略。

1.2 多行数据 + 指定列插入

sql 复制代码
INSERT [INTO] 表名 (列名1 [, 列名2, ..., 列名n])] VALUES (值1, 值2, ..., 值n) [, (值1, 值2, ..., 值n)];

• 可以一次性向表中插入多条数据,插入的多条数据之间使用逗号 隔开。

• 插入多行数据时,可以对指定列进行插入,也可以进行全列插入,这里就只演示对指定的 sn、name 列进行插入。

• 注:在对指定列插入数据时,只有允许为空的字段和设置了自增长属性的字段能不指定值插入,不允许为空的字段必须指定值插入

单行数据指定列属性插入

多行指定插入指定列属性插入

1.3 插入否则更新

由于主键 或者唯一键对应的值已经存在而导致的插入失败。

此时如果我们需求是,如果存在,让新的数据更新旧的数据;如果不存在,直接插入当前数据。此时,我们如果要实现该需求就需要使用insert的插入否则更新了。

• 语法格式

sql 复制代码
INSERT ... ON DUPLICATE KEY UPDATE 列名1 = 值1 [, 列名2 = 值2, ..., 列明n = 值n];
// 语句中的 字段=值,表示当插入数据时,如果出现冲突则需要更新的字段值。

我们再来分别试一下,不冲突和冲突的情况。

• 根据影响行数判断插入情况

0 row affected :表中有冲突数据,但是冲突的值和update的值是一样的。

1 row affected :表中没有冲突数据,数据被成功插入。

2 row affected :表中有冲突数据,并且数据已经被更新。

可以使用 ROW_COUNT();函数获取受影响的行数

1.4 插入否则替换

sql 复制代码
REPLACE INTO 表名 [(列名1 [, 列名2, ..., 列名n])] VALUES (值1, 值2, ..., 值n) [, (值1, 值2, ..., 值n)];
// 只是将 插入数据  语法中的 INSERT 替换成了 REPLACE 而已

• 当 主键 或者 唯一键 没有冲突时,则直接插入,此时和insert 一样

• 当 主键 或者 唯一键 有冲突时,先删除原来的冲突条目,然后再将新条目数据插入

无冲突的情况就是insert

有冲突的情况,先删除在插入

根据表的影响行数判断替换情况

• 1 row affected:表中没有发生数据冲突,数据直接被插入。

• 2 row affected:表中发生了数据冲突,表中的冲突数据被删除后插入了新的数据

二、select 查询

语法格式

sql 复制代码
SELECT [DISTINCT] {* 或 {列名1 [, 列名2, ..., 列名n] ...}} FROM 表名 [WHERE ...] [ORDER BY ...] [LIMIT ...];

准备工作

为了后续的操作,我们先来创建一张成绩表。

表中字段:id为主键且自增、学生姓名name不为空、语文成绩chinese 默认、数学成绩math默认、英语成绩english默认属性。

sql 复制代码
CREATE TABLE exam_result (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL COMMENT '同学姓名',
    chinese float DEFAULT 0.0 COMMENT '语文成绩',
    math float DEFAULT 0.0 COMMENT '数学成绩',
    english float DEFAULT 0.0 COMMENT '英语成绩'
);

然后在向表中插入一批数据:

2.1 select 列

2.1.1 全列查询

就是将表中的条目的全列数据全部读取出来。

sql 复制代码
SELECT [DISTINCT] * FROM 表名 [WHERE ...] [ORDER BY ...] [LIMIT ...];

这里的 *****标示通配符的意思。

通常情况下 建议使用 *****进行全列查询,原因如下:

1、一般MySQL的服务是部署在某台主机上的,查询的越多,意味着需要传输的数据量越大,需要的网络资源也就越多

2、可能会影响到索引的使用

2.1.2 指定列查询

在查询数据时也可以只对指定的某些列进行查询

指定列的顺序 不一定和定义表 的顺序一致

2.1.3 查询字段为表达式

select 是个很特殊的关键字,它可以是 select 自带的各种子句、指定表的字段名、普通表达式等。

select 不仅能够用来查询数据,还可以用来计算某些表达式的值或执行某些函数

当然可以使用复合字段进行求总分

2.1.4 为查询的结果指定别名

• 可以给表的某一列取个别名,用来更好的分辨某一列的功能。

• 对列做重命名属于显示的范畴,是最后一步已经拿完数据了,只是做个改名操作而已,只能在 select 语句这里进行重命名。

注意: 执行顺序在 select 之前的子句无法对列取别名

sql 复制代码
SELECT 指定列名 [AS] 指定列的别名 [...] FROM 表名;

上面的总分为例,我们可以对他进行重命名:

当然as是可以省略的

2.1.5 结果去重
sql 复制代码
SELECT DISTINCT 字段列表 from 表名;

查询结果中可能有重复的数据,如果我们期望查询的结果没有重复的数据,就可以指定 distinct

注意 :这里是一列进行去重的,如果是全列/多列的话,就需要每条数据的全列/多列数据值都相同才会进行去重!另外 distinct 一般可以配合聚合函数count()进行统计不重复条目的数量。关于聚合函数,下面会介绍。

2.2 where 条件

1、在查询时,也不是每次都要查询表中所有的行的数据 ,还需要根据一些筛选条件查看 指定行的数据。where 筛选影响的是显示出来的行数。

2、在查询数据时如果使用了 where 子句,则会先根据 where 子句筛选出符合条件的行数据,然后将符合条件的行数据作为数据源依次执行 select 语句,从而找出符合条件的列数据

2.2.1 运算符介绍

where 子句可以指定 1/ n 个筛选条件,where 使用特定的比较运算符逻辑运算符类决定如何进行筛选

比较运算符

逻辑运算符

2.2.2 使用案例

下面我将使用以下9个案例来使用where和运算符

1、查询英语不及格的同学及其英语成绩。

2、查询语文成绩在 [80, 90] 分之间的同学及其语文成绩。

3、查询数学成绩是 58 或者是 59 或者是 98 或者是 99 分的同学及其数学成绩。

4、查询姓赵的同学以及赵某同学。

5、查询语文成绩优于英语成绩的同学。

6、查询总分在 200 分以下的所有同学的信息。

7、查询语文成绩 > 80 并且不姓李的同学。

8、查询重某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 60 分。

9、NULL 的查询。

1、查询英语不及格的同学及其英语成绩。

where 子句指定的筛选条件是 english < 60, select 指明要查询的字段是 name、english

2、查询语文成绩在 [80, 90] 分之间的同学及其语文成绩。

where 子句的筛选条件是 chiese >= 80 && chinese <=90, select指定的查询字段是 name,chinese

当然这里where子句的筛选条件也可以使用 between a and b即 between 80 and 90

3、查询数学成绩是 58 或者是 59 或者是 98 或者是 99 分的同学及其数学成绩。

where 子句的筛选条件是 math=58 || math=59 || math=98 || math=99,select 指定的查询列字段是 name,math

当然这里的 where子句的筛选条件也可以使用 in(a1,a2,a3,a4...) 即in(58,59,98,99)

4、查询姓赵的同学以及赵某同学。

where 子句的筛选条件是 模糊模糊匹配 姓赵的同学,名字可以有多个字(使用%,不管多少个子字都可以匹配) :赵% ,赵某,名字只有一个字(使用_,只能匹配一个字): 赵_ ,select 查询的字段是 name

当前表中没有姓赵的,我先插入几个:

下面来查询一下:

5、查询语文成绩优于英语成绩的同学。

where 子句的筛选条件:chinese > english ,select指定的查询列字段是 name,chinese,english


6、查询总分在 200 分以下的所有同学的信息。

where 子句的筛选条件:chinese+math+english < 200 ,select 的查询列字段是 name,总分

7、查询语文成绩 > 80 并且不姓李的同学。

where 子句的筛选条件:chinese>80 && name not like '李%' ,select 的查询列字段是 name,chinese


8、查询重某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 60 分。

where 子句的筛选条件:(name like '重_')||(chinese+math+english >200 && chinese > math && english > 60) ,select 的查询列字段是 name,chinese,math,english,总分

先下入两个姓重的同学

下面进行查询


9、NULL 的查询。

这里为了方便演示,我们使用前面的students表:

查询 qq 号已知的同学:即查询 qq 号is not null不为空的同学。

这里不能使用 != 即 qq != null 过滤,原因在下面

查询 qq 号未知的同学,即查询 qq 号 is null 为空的同学。

同理这里也不能使用 = 过滤,即qq=null

上面不能使用 = 和 != 和 null原因是不安全的=和!=直接和 null比较/运算的结构都是 null

null判断null可以使用is null / <=>

这里更加推荐 is null

null判断非null使用 is not null

2.2.3 order by 结果排序

由于查询的结果是个表结构,可能会有多行信息,通常将一行数据称之为记录,有些情况下就需要对这些筛选出来的记录进行排序。

语法格式

sql 复制代码
SELECT ... FROM 表名 [WHERE ...] ORDER BY 字段1 [ASC 或 DESC], [...];

• ASC 表示升序,DESC 表示降序,默认 为升序 ASC。

• 如果查询语句中没有 order by 子句,则返回的顺序是未定义的。

• 可以根据多个字段进行排序,当根据字段 1 的值排序完之后出现了重复值,则再根据字段 2 的值对重复的部分排序,以此类推。

order by 的使用案例

下面我们将使用以下的5个案例来说明并练习 order by 排序

1、查询所有的同学及其数学成绩,查询结果按 数学成绩 升序显示。

2、查询所有的同学及其 qq 号,查询结果按 qq 号排序显示。

3、查询同学的各门成绩,查询结果依次按 数学降序、英语升序、语文升序 的方式进行显示。

4、查询所有同学的成绩总分,查询结果按 总分 降序显示。

5、查询姓 赵 的的同学或者姓 王 的同学的数学成绩,查询结果按 数学成绩 降序显示。

1、查询所有的同学及其数学成绩,查询结果按 数学成绩 升序显示。

order by 子句中按照 math 按照 升序排列, select 查询列字段是 name 和 math

注意:默认不写 就是 asc 升序,这里也是可以不写asc的

2、查询所有的同学及其 qq 号,查询结果按 qq 号排序显示。

注意这里使用的是 students表:

order by 子句中按照 qq 按照 升序排列, select 查询列字段是 name 和 qq

3、查询同学的各门成绩,查询结果依次按 数学降序、英语升序、语文升序 的方式进行显示。

在 order by 子句中指明依次按照 math desc, english asc, chinese asc 进行排序,在 select 的字段列表中指明要查询的列为 name、math、english 和 chinese
首先按照数学成绩进行降序排序的,在相同的数学成绩之间按照英语进行升序排序。

4、查询所有同学的成绩总分,查询结果按 总分 降序显示。

order by 子句筛选条件 chinese+math+english desc,select 查询列属性字段 name 和 总分

5、查询姓 赵 的同学或者姓 王 的同学的数学成绩,查询结果按 数学成绩 降序显示。

where 子句 的筛选条件是 name like '赵%' || name like '王%', order by 子句 排序条件 math desc,select 查询列属性字段 name 和 math

2.2.4 limit 分页查询

有时候一张表中的数据可能太多了,不方便看,此时就需要对这张表中的数据进行分页显示,例如网站的第几页那就是分页显示。

limit 语法格式

从0行开始向后筛选n行

sql 复制代码
SELECT ... FROM 表名 [WHERE ..] [ORDER BY ...] LIMIT n;

从第 s 行数据开始,向后筛选出 n 行数据

sql 复制代码
SELECT ... FROM 表名 [WHERE ...] [ORDER BY ...] LIMIT s, n

从第 s 行数据开始,向后筛选出 n 行数据 (比第二种用法更明确,建议使用)。

sql 复制代码
SELECT ... FROM 表名 [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;

注意:limit 子句在筛选记录时,记录的下标从 0 开始,即第一行数据的下标为 0。

建议:对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死。

limit 分页案例

下面我将使用两个案例来说明,limit 分页

1、按 id 对成绩表进行分页,每页 3 行数据,分别显示第 1、2、3 页。

2、查询班级总分第一名的学生

1、按 id 对成绩表进行分页,每页 3 行数据,分别显示第 1、2、3 页。

第一页就是,从0条记录开始筛选3条记录;写法有三种:

第二页 从第3号记录开始,往后筛选3条记录

第三页 从6号记录开始,显示3条数据

2、查询班级总分第一名的学生

先通过order by子句对总成绩进行降序排序,然后使用 limit 进行获取第一个就是分数最高的

这里有个细节 就是在这里我们在 order by 这里直接使用了 别名,这和SQL查询的顺序是有关系 的,这里先记住 order by 的执行顺序是 select 之前。具体的后面会总结的!

三、Update 更新

语法格式

sql 复制代码
update table_name set 列属性1=值1 [,列属性2=值2,...] [where] [order by] [limit]

作用对查询到的结果进行列值的更新

3.1 使用案例

我们这里还是以 exam_result 表为例,进行演示!将以下面的4个案例进行演示。

1、将孙悟空同学的数学成绩更新为80分

2、将曹孟德同学的数学成绩更新为60分,语文成绩更新为 70分

3、将总成绩倒数前三的3位同学的数学成绩加上30分

4、将所有同学的语文成绩更新为原来的2倍

1、将孙悟空同学的数学成绩更新为80分

2、将曹孟德同学的数学成绩更新为60分,语文成绩更新为 70分

3、将总成绩倒数前三的3位同学的数学成绩加上30分

这里就将结果更新出来了,但是这里有两个细节问题需要注意!

1、MySQL中没有 += 这样的操作,所以我们数学+30分只能写成 math = math + 30;

2、在 Update语句中,其与 select 不同的是 update 支持 limit 的部分,支持 limit n 不支持 limit s,n,limit n offset s; limit n表示限制的行数, 而 limit s,n,limit n offset s 用于进行分页。

3、update 中的 order by 和 limit 主要是用于限制更新的行数,而不是基于分页更新。

演示 limit s,n,limit n offset s;不能进行更新结果:

4、将所有同学的语文成绩更新为原来的2倍

因为这里是全列的修改,比较大;所以我们先来查询一下修改之前的数据

下面是修改以及修改后的结果:

注意:全列的修改操作得非常慎重进行!!!

四、Delect 删除

语法格式

sql 复制代码
delete from table_name [where] [order by] [limit]

作用:删除表中的数据 ;不带限制条件 删除的为整个表中的数据。

4.1 删除数据

这里使用下面的这个案例演示。

4.1.1 删除指定的数据

删除孙悟空同学的成绩

4.1.2 删除整张表

1、当 delete 删除的时候不指定限制条件的时候会将整个表中的数据删除,注意delete删除的是整张表的数据,而删除表的操作是 drop table table_name;

2、删除整张表的操作要慎重

准备工作:

1、创建一张测试表 for_delete

2、插入一批数据

OK,此时表有了,数据也有了,就可以测试删除整张表的数据了!

此时显示的为空,说明已将他的全部数据已删除。但是我们这里个问题:这里全部删除后,再次插入后主键ID是从原先的开始递增,还是从0开始递增?

我们新增一条数据后发现他的id是4就是上一次的+1,也就是说我们删除表的数据后主建是不会置0 的!

4.2 截断表

语法格式

sql 复制代码
truncate [table] table_name;

作用:将整个表的数据全部删除,但是与 delete 有区别;

1、truncate 只能对表整体做删除,不能删除单独的一条/一部分数据;

2、truncate 比 delete 更快的原因是,truncate是不走事务,所以后期也无法回滚;

3、truncate会重置 auto_increment 选项

我们还是先来创建一个测试表for_truncate

插入一批数据:

执行truncate for_truncate 进行对表截断:

我们再来插入一条数据,验证一下 auto_increment 选项是否重置:

五、插入查询结果

语法格式

sql 复制代码
insert into table_name [列属性] select ...

作用:将一个表中的查询结果直接插入到结构相同的表中;

这里还是一个案例演示:删除表中的重复记录,重复的数据值只能有一份

1、创建表 duplicate_table,并插入一批数据含重复

准备工作做完,下面就是去重的操作了!

思路:创建一张和 duplicate_table结构一样的表no_duplicate_table,然后通过select的去重选项distinct 进行去重查询,然后将结果插入到no_duplicate_table中,然偶使用rename进行对他们相互重命名(原子操作),之后的duplicate_table中就是去重后的数据。

1、常见一张和duplicate_table结构一样的表no_duplicate_table:

这里直接使用like进行创建相同结构的表。

2、使用select 和 distinct进行去重操作

查看一下

3、对两个表进行重命名,实现原子的去重操作

六、聚合函数

6.1 什么是聚合函数

聚合函数 是一类用于对一组数据进行统计和计算的函数。他们能够对表中的数据进行多行统计求和、求平均值等操作。

聚合函数一般配合group by子句使用,也可以单独使用。关于group by子句后面单独介绍,这里先单独使用。

常见的函数如下:

注意 :聚合函数和 select 一起使用的时候,select会将每一条处理记录的结果以参数的形式传递给聚合函数!

6.2 使用案例

下面将以 7 个案例说明,使用 syudents 表 和 exam_result 表进行说明

1、统计班级共有多少个学生

2、统计班级收集的QQ号有多少

3、统计本次考试的数学成绩分数个数

4、统计数学成绩总分

5、统计平均总分

6、返回英语最高分

7、返回 > 70分以上的数学最低分

1、统计班级共有多少个学生

使用 *****作统计

*表示通配符,代表的是表中所有条目(所有人)的信息,将其通过select 查询到之后,传递给count函数,就可以统计处有多少人。

使用表达式统计

这种写法的意思是,给每一个条目都添加了一列特定名的表达式 ,然后让count统计该列中有多少数据,即变相的统计了一共有多少条目,这里的表达是就是一个数字。

2、统计班级收集的QQ号有多少

ps: count 函数不对NULL做统计

3、统计本次考试的数学成绩分数个数

这里统计的是数学成绩的分数个数,也就是所有人的数学成绩,这里是不包含去重的

如果我们这里想统计去重后数学成绩的个数呢?可以使用 distinct 修饰 math:

4、统计数学成绩总分

直接将数学作为参数传递给sum函数即可

统计不及格(<90)的数学成绩的总分

这里我们可以在上面的基础上,进行 where 条件筛选,然后将符合条件的条目的数学成绩给sum函数计算:

5、统计平均总分

总分的平均分可以使用 avg函数,将chinese+math+english的结果传递给avg即可!

6、返回英语最高分

使用 max函数对全表的 english 进行计算

7、返回 > 70分以上的数学最低分

首先通过 min函数获取数学的最低分,然后使用 where 子句限定是 70分以上的

七、group by 子句分组

在select 中使用 group by 子句可以对指定列进行分组查询。

分组的作用是通过分组之后方便进行聚合统计。

7.1 语法格式

sql 复制代码
SELECT column1 [, column2], ... FROM table_name [WHERE ...] GROUP BY column [, ...] [order by ...] [LIMIT ...];

注意 :group by 后面跟的,表是根据 指定列对整张表进行分组。

7.2 使用案例

a、预备工作

我们需要对雇员信信息表的表进行分组查询,雇员信息数表中包含三张表:员工表 (emp)、部门表 (dept) 和 工资等级表(salgrade)。

**员工表(emp)**中包含如下字段:

雇员编号(empno)

雇员姓名(ename)

雇员职位(job)

雇员领导编号(mgr)

雇佣时间(hiredate)

工资月薪(sal)

奖金(comm)

部门编号(deptno)

**部门表(dept)**中包含如下字段:

部门编号(deptno)

部门名称(dname)

部门所在地点(loc)

**工资等级表(salgrade)**中包含如下字段:

等级(grade)

此等级最低工资(losal)

此等级最高工资(hisal)

三张表的信息的相关SQL语句如下:

sql 复制代码
DROP database IF EXISTS `scott`;
CREATE database IF NOT EXISTS `scott` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

USE `scott`;

DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
  `deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
  `dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
  `loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
);


DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
  `empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
  `ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
  `job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
  `mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
  `hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
  `sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
  `comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
  `deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
);


DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (
  `grade` int(11) DEFAULT NULL COMMENT '等级',
  `losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
  `hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
);


insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept (deptno, dname, loc)
values (20, 'RESEARCH', 'DALLAS');
insert into dept (deptno, dname, loc)
values (30, 'SALES', 'CHICAGO');
insert into dept (deptno, dname, loc)
values (40, 'OPERATIONS', 'BOSTON');

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7844, 'TURNER', 'SALESMAN', 7698,'1981-09-08', 1500, 0, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);

insert into salgrade (grade, losal, hisal) values (1, 700, 1200);
insert into salgrade (grade, losal, hisal) values (2, 1201, 1400);
insert into salgrade (grade, losal, hisal) values (3, 1401, 2000);
insert into salgrade (grade, losal, hisal) values (4, 2001, 3000);
insert into salgrade (grade, losal, hisal) values (5, 3001, 9999);

我们可以看看三张表:

部门表

雇员表

薪资等级表

b、分组查询

1、如何显示每个部门的平均工资和最高工资

实现思路:根据部门对整个员工表进行分组,然后对分组的 "表" 进行聚合查询/统计

2、显示每个部门的每种岗位的平均工资和最低工资

实现思路:先根据部门对整张雇员表进行分组,然后在此基础上在根据 工种 二次分组,然后在对其进行聚合统计

注意:

1、二次分组是在上一次分组的基础上使用 ,号跟在后面。

2、分组后 select 中出现的列是 分组中出现的列属性,其他属性不能出现。

验证上述的第二点:他这里显示不认识name列属性,原因在于分组的目的是为了聚合统计!

3、显示平均工资低于 2000 的部门和它的平均工资

我们分两步来:1、显示不同部门的平均工资 2、显示在第一步分组筛选出来结果的基础上进行使用having条件进行筛选出 平均工资小于 2000 的部分

1、显示不同部门的平均工资

2、显示在第一步分组筛选出来结果的基础上进行使用having条件进行筛选出 平均工资小于 2000 的部分

这里有一个筛选的条件 having 前面学了一个 条件筛选 where 这两有啥区别呢?下面来区别一下:

7.3 having 和 where 的区别?

1、having 作用是对分组的聚合后的结果进行条件筛选,having 经常和 group by 配合使用。

2、where 是对表中任意列进行条件筛选

3、在对整张表进行筛选时,可以使用 where 也可以使用 having(但是不推荐使用having)

4、在对分组聚合的结果进行条件筛选时,不能使用 where 只能使用 having

7.4 分组的理解

1、group by 按照指定列分组,实际分组的是按照该列的不同值进行对数据分组。

2、同一以分组条件分成的某一组,其分组条件的那一列的值一定相同。

3、分组不就是把一组数据按照一定的条件分成多组,然后在组内聚合统计。

4、分组("分表")不就是把一张表按照特定条件在逻辑上成分成多个子表,然后分别对各个子表进行聚合统计。

7.4 理解MySQL一切皆表

不要单纯的认为,只有磁盘上的表结构导入到mysql,真实存在的表才叫表。在中间各筛选条件筛选出来的,包括最终结果,在我们看来,全都是逻辑上的表(临时表),所以我们在未来进行对不同组筛选可以看成是对特定表的筛选。
面试题:SQL查询中各个关键字的执行顺序
from > on> join > where > group by > with > having > select > distinct > order by > limit

相关推荐
镜舟科技8 分钟前
如何高效使用 Text to SQL 提升数据分析效率?四个关键应用场景解析
数据库·sql·数据分析
玛奇玛丶17 分钟前
数据库索引失效了...
后端·mysql
King.62440 分钟前
数据服务化 VS 数据中台:战略演进中的价值重构
大数据·数据库·sql·oracle·重构
Elastic 中国社区官方博客41 分钟前
Elasticsearch:AI 助理 - 从通才到专才
大数据·数据库·人工智能·神经网络·elasticsearch·搜索引擎·全文检索
花千树-0101 小时前
MySQL 数据库备份和恢复全指南
数据库·mysql
·薯条大王1 小时前
Node.js 操作 MySQL 数据库
javascript·数据库·mysql
Java_SuSheng1 小时前
关于SQLite轻量数据库的研究
java·数据库·spring boot·sqlite·mybatis
maomi_95263 小时前
数据库学习通期末复习二
服务器·数据库
努力努力再努力wz3 小时前
【Linux实践系列】:用c/c++制作一个简易的进程池
linux·运维·数据库·c++·c
fly spider4 小时前
一站式Windows下Docker开启MySQL并链接本地Navicat(附乱码解决方案)
windows·mysql·docker·乱码解决