前言
前面我们对表结构做了介绍,本期我们对表的内容操作机增删改查进行介绍!
目录
前言
一、insert 插入
1.1 单行数据 + 全列插入
1.2 多行数据 + 指定列插入
1.3 插入否则更新
1.4 插入否则替换
二、select 查询
2.1 select 列
2.1.1 全列查询
2.1.2 指定列查询
2.1.3 查询字段为表达式
2.1.4 为查询的结果指定别名
2.1.5 结果去重
2.2.1 运算符介绍
2.2.2 使用案例
2.2.3 order by 结果排序
2.2.4 limit 分页查询
三、Update 更新
3.1 使用案例
四、Delect 删除
4.1 删除数据
4.1.1 删除指定的数据
4.1.2 删除整张表
4.2 截断表
五、插入查询结果
六、聚合函数
6.1 什么是聚合函数
6.2 使用案例
七、group by 子句分组
7.1 语法格式
7.2 使用案例
7.3 having 和 where 的区别?
7.4 分组的理解
7.4 理解MySQL一切皆表
一、insert 插入
• 语法格式
INSERT [INTO] table_name [(列属性字段1)(,列属性字段2)...] VALUES(value_list)[, (value_list)]...;
• 准备工作
为了方便演示后续的操作,我们先来创建一张学生表。
表中字段有:id主键自增、学号sn唯一键且不为空、姓名name不为空、以及唯一键qq。
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 单行数据 + 全列插入
INSERT [INTO] table_name [(列属性字段1)(,列属性字段2)...] VALUES(value_list);
• 向表中插入一行数据,插入时需要和指定列字段属性(默认列属性字段)的顺序一致。
• 列属性字段属性列表在全列插入时可以省略。
• insert 操作时 into 可以省略
向表中插入一行数据,插入时需要和指定列字段属性(默认列属性字段)的顺序一致。
列属性字段属性列表在全列插入时可以省略。
insert 操作时 into 可以省略。
1.2 多行数据 + 指定列插入
INSERT [INTO] 表名 (列名1 [, 列名2, ..., 列名n])] VALUES (值1, 值2, ..., 值n) [, (值1, 值2, ..., 值n)];
• 可以一次性向表中插入多条数据,插入的多条数据之间使用逗号隔开。
• 插入多行数据时,可以对指定列进行插入,也可以进行全列插入,这里就只演示对指定的 sn、name 列进行插入。
• 注:在对指定列插入数据时,只有允许为空的字段和设置了自增长属性的字段能不指定值插入,不允许为空的字段必须指定值插入
单行数据指定列属性插入
多行指定插入指定列属性插入
1.3 插入否则更新
由于主键或者唯一键对应的值已经存在而导致的插入失败。
此时如果我们需求是,如果存在,让新的数据更新旧的数据;如果不存在,直接插入当前数据。此时,我们如果要实现该需求就需要使用insert的插入否则更新了。
• 语法格式
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 插入否则替换
REPLACE INTO 表名 [(列名1 [, 列名2, ..., 列名n])] VALUES (值1, 值2, ..., 值n) [, (值1, 值2, ..., 值n)];
// 只是将 插入数据 语法中的 INSERT 替换成了 REPLACE 而已
• 当 主键 或者 唯一键 没有冲突时,则直接插入,此时和insert 一样
• 当 主键 或者 唯一键 有冲突时,先删除原来的冲突条目,然后再将新条目数据插入
无冲突的情况就是insert
有冲突的情况,先删除在插入
根据表的影响行数判断替换情况
• 1 row affected:表中没有发生数据冲突,数据直接被插入。
• 2 row affected:表中发生了数据冲突,表中的冲突数据被删除后插入了新的数据
二、select 查询
语法格式
SELECT [DISTINCT] {* 或 {列名1 [, 列名2, ..., 列名n] ...}} FROM 表名 [WHERE ...] [ORDER BY ...] [LIMIT ...];
准备工作
为了后续的操作,我们先来创建一张成绩表。
表中字段:id为主键且自增、学生姓名name不为空、语文成绩chinese 默认、数学成绩math默认、英语成绩english默认属性。
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 全列查询
就是将表中的条目的全列数据全部读取出来。
SELECT [DISTINCT] * FROM 表名 [WHERE ...] [ORDER BY ...] [LIMIT ...];
这里的 * 标示通配符的意思。
通常情况下 不建议使用 * 进行全列查询,原因如下:
1、一般MySQL的服务是部署在某台主机上的,查询的越多,意味着需要传输的数据量越大,需要的网络资源也就越多
2、可能会影响到索引的使用
2.1.2 指定列查询
在查询数据时也可以只对指定的某些列进行查询
指定列的顺序 不一定和定义表 的顺序一致
2.1.3 查询字段为表达式
select 是个很特殊的关键字,它可以是 select 自带的各种子句、指定表的字段名、普通表达式等。
select 不仅能够用来查询数据,还可以用来计算某些表达式的值或执行某些函数
当然可以使用复合字段进行求总分
2.1.4 为查询的结果指定别名
• 可以给表的某一列取个别名,用来更好的分辨某一列的功能。
• 对列做重命名属于显示的范畴,是最后一步已经拿完数据了,只是做个改名操作而已,只能在 select 语句这里进行重命名。
注意:执行顺序在 select 之前的子句无法对列取别名
SELECT 指定列名 [AS] 指定列的别名 [...] FROM 表名;
上面的总分为例,我们可以对他进行重命名:
当然as是可以省略的
2.1.5 结果去重
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 结果排序
由于查询的结果是个表结构,可能会有多行信息,通常将一行数据称之为记录,有些情况下就需要对这些筛选出来的记录进行排序。
语法格式
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行
SELECT ... FROM 表名 [WHERE ..] [ORDER BY ...] LIMIT n;
从第 s 行数据开始,向后筛选出 n 行数据
SELECT ... FROM 表名 [WHERE ...] [ORDER BY ...] LIMIT s, n
从第 s 行数据开始,向后筛选出 n 行数据 (比第二种用法更明确,建议使用)。
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 更新
语法格式
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 删除
语法格式
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 截断表
语法格式
truncate [table] table_name;
作用:将整个表的数据全部删除,但是与 delete 有区别;
1、truncate 只能对表整体做删除,不能删除单独的一条/一部分数据;
2、truncate 比 delete 更快的原因是,truncate是不走事务,所以后期也无法回滚;
3、truncate会重置 auto_increment 选项
我们还是先来创建一个测试表for_truncate
插入一批数据:
执行truncate for_truncate 进行对表截断:
我们再来插入一条数据,验证一下 auto_increment 选项是否重置:
五、插入查询结果
语法格式
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 语法格式
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语句如下:
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查询中各个关键字的执行顺序