单表查询
前期表准备
create table emp(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male',
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int,
depart_id int
);
# 插入数据
# 三个部门:教学,销售,运营
insert into
emp(name,sex,age,hire_date,post,salary,office,depart_id)
values
("jaosn","male",18,"20170301","张江第一帅形象代言",7300.33,404,1),
("egon","male",78,"20150302","teacher",1000000.31,401,1),
("kevin","male",81,"20130305","teacher",8300,401,1),
("tank","male",73,"20140701","teacher",3500,401,1),
("owen","male",28,"20121101","teacher",2100,401,1),
("jerry","female",18,"20110211","teacher",9000,401,1),
("nick","male",18,"19000301","teacher",30000,401,1),
("sean","male",48,"20101111","teacher",10000,401,1),
("歪歪","female",48,"20150311","sale",3000.13,402,2),
("丫丫","female",38,"20110312","sale",2000.35,402,2),
("丁丁","female",18,"20110312","sale",1000.37,402,2),
("星星","female",18,"20160513","sale",3000.29,402,2),
("格格","female",28,"20170127","sale",4000.33,402,2),
("张野","male",28,"20160311","operation",10000.13,403,3),
("程咬金","male",18,"19970312","operation",20000,403,3),
("程咬银","male",18,"20130311","operation",19000,403,3),
('程咬铜',"male",18,"20150411","operation",18000,403,3),
("程咬铁","female",18,"20140512","operation",17000,403,3)
;
# ps:如果在window系统中,插入中文字符,select的结果为空白,可以将所有字符编码统一设置成gbk
1.语法执行顺序
书写顺序
select id,name from emp where id > 3 and id < 6;
执行顺序
from # 确定到底是哪张表
where # 根据条件,筛选数据
select # 取出筛选出来的数据中的某些字段
select * from empG; # 当表字段特别多的时候,结果的排版可能会出现混乱的现象,你可以在查询语句加G来规范查询结果
2.where约束条件
# 1.查询id大于等于3小于等于6的数据
select * from emp where id >= 3 and id <= 6;
select * from emp where id between 3 and 6;
# 2.查询薪资是20000或则18000或则17000的数据
select * from emp where salary = 2000 or salary = 18000 or salary = 17000;
select * from emp where salary in (20000,17000,18000);
# 3.查询员工姓名中包含o字母的员工姓名和薪资
# 模糊匹配 like
%:匹配多个任意字符
_:匹配一个任意字符
select name,salary from emp where name like "%o%";
# 4.查询员工姓名是由四个字符组成的员工姓名与其薪资
select name,salary from emp where name like "____";
select name,salary from emp where char_length(name) = 4;
# 5.查询id小于3或者大于6的数据
select * from emp where id not between 3 and 6;
select * from emp where id < 3 or id > 6;
# 6.查询薪资不在20000,18000,17000范围的数据
select * from emp where salary not in (20000,18000,17000);
# 7.查询岗位描述为空的员工名与岗位名 针对null不能用等号,只能用is
select name,post from emp where post_comment = NULL; # 查询为空
select name,post from emp where post_comment is NULL;
select name,post from emp where post_comment is not NULL; # 查询为空
# 注意:MySQL对大小不敏感
3.group by
MySQL中分组之后,只能拿到分组的字段信息,无法直接获取其他字段信息,但是可以通过其他方法(聚合函数)简介的获取。
1.count():计数,为null时不会计入
2.sum():求和
3.avg():求平均书,为null时不计入分母
4.max():求最大值
5.min():求最小值
以上聚合函数可以写在字段的位置,或则是分组的后面
# 数据分组应用场景:每个部门的平均薪资,男女比例
# 1.按部门分组
select * from emp group by post; # 分组后取出的是每个组的第一条数据的字段
# 注意:分组之后应该做到最小单位是组,而不应该再展示组内的单个数据信息,此时我们可可以添加ONLY_FULL_GROUP_BY到sql_mode中避免这个问题
如果你的MySQL不报错,说明严格模式没有设置
show variables like "sql_mode";
set session 当前创口有效
set global sql_mode = "strict_trans_tables,only_full_group_by";
设置好之后
select * from emp group by post; # 报错
select id,name,sex from emp group by post; # 报错
select post from emp group by post; # 获取部门信息
# 强调:只要分组了,就不能够再"直接"查找到单个数据信息了,只要获取到组名
# 2.获取每个部门的最高工资
# 以组为单位统计组内数据>>>聚合查询(聚集到一起合成为一个结果)
# 每个部门的最高工资
select post,max(salary) from emp group by post;
# 每个部门的最低工资
select post,min(salary) from emp group by post;
# 每个部门的平均工资
select post,avg(salary) from emp group by post;
# 每个部门的工资总和
select post,sum(salary) from emp group by post;
# 每个部门的人数
select post,count(id) from emp group by post;
select post,count(age) from emp group by post;
select post,count(salary) from emp group by post;
select post,count(post_comment) from emp group by post; # 人数为0
# 注意:在统计分组内个数的时候,填写任意非空字段都可以完成计数,推荐使用能够唯一标识数据的字段,比如id字段
# 3.查询分组之后的部门名称和每个部门下所有的学生姓名
# group_concat(分组之后用) 不仅可以用来显示除分组外字段还有拼接字符串的作用
select post,group_concat(name) from emp group by post;
select post,group_concat("DSB",name) from emp group by post;
select post,group_concat(name,":",salary) from emp group by post;
select post,group_concat(salary) from emp group by post;
# 4.补充concat(不分组时用)拼接字符串达到更好的显示效果 as语法使用
select name as 姓名,salary as 薪资 from emp;
select concat("NAME:",name) as 姓名,concat("SAL:",salary)
as 薪资 from emp;
# 补充as语法,即可以给字段起别名也可以给表起
select emp.id,emp.name from emp as t1; # 报错,因为表名已经被改成了t1
select t1.id,t1.name from emp as t1;
# 查询四则运算
# 查询每个人的年薪
select name,salary*12 as annual_salary from emp;
select name,salary*12 as annual_salary from emp; # as可以省略
刚开始查询表,一定要按照最基本的步骤,先确定是哪张表,再确定查这张表也没有限制条件,再确定是否需要分类,最后再确定需要什么字段对应的信息
你应该将每一步操作产生的结果都当成是一张新的表,然后基于该表再进行其他的操作
练习题
# 刚开始查询表,一定要按照最基本的步骤,先确定是哪张表,再确定查这张表也没有限制条件,再确定是否需要分类,最后再确定需要什么字段对应的信息
# 1.查询岗位名以及岗位包含的所有员工名字
select post,group_concat(name) from emp group by post;
# 2.查询岗位名以及各岗位内包含的员工个数
select post,count(id) from emp group by post;
# 3.查询公司内男员工和女员工的个数
select sex,count(id) from emp group by sex;
# 4.查询岗位名以及各岗位的平均薪资
select post,avg(salary) from emp group by post;
# 5.查询岗位名以及各岗位的最高薪资
select post,max(salary) from emp group by post;
# 6.查询岗位名以及各岗位的最低薪资
select post,min(salary) from emp group by post;
# 7.查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
select sex,avg(salary) from emp group by sex;
# 8.统计各部门年龄在30岁以上的员工平均工资
select post,avg(salary) from emp where age > 30 group by post;
"""
写sql语句的时候,一定不要一口气写完,前期先按照步骤一步步写,写一步查询看一下结果然后基于当前结果再往后写
"""
4.having
having的语法格式与where一致,只不过having是在分组之后进行的过滤,即where虽然不能用聚合函数,但是having可以!
select 查询条件1,查询条件2,...from 表名
where 过滤条件
group by 分组依据
# 语法这么写,但是执行顺序却不一样
# 执行顺序
from
where
group
select
# 1.统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门
select post,avg(salary) from emp
where age >= 30
group by post
having avg(salary) > 10000;
select post,avg(salary) from emp
where age >= 30
group by post
where avg(salary) > 10000; # 报错
# 强调:having必须在group by后面使用
select * from emp having avg(salary) > 10000; # 报错
5.distinct 去重
去重必须是一模一样的才能去重,只要有一个不一样,都不能算是重复的数据。
# 对有重复的展示数据进行去重操作
select distinct post from emp;
select distinct id,age from emp;
执行顺序
from
where
group by
having
select
distinct
6.order by 排序
默认是升序asc
,也可以变成降序desc
select * from emp order by salary asc; # 默认升序排
select * from emp order by salary desc; # 降序排
select * from emp order by age desc; # 降序排
# 先按照age降序排,在年龄相同的情况下再按照薪资升序排
select * from emp order by age desc,salary asc;
# 统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资进行排序
select post,avg(salary) from emp
where age > 10
group by post
having avg(salary) > 1000
order by avg(salary)
;
7.limit 限制
limit 限制展示数据的条数
当limit只有一个参数的时候,表示的是只展示几条
当limit有两个参数的时候,第一个参数表示的是起始位置,第二个参数表示从起始位置开始往后展示的条数。
# 限制展示条数
select * from emp limit 3;
# 查询工资最高的人的详细信息
select * from emp order by salary desc limit 1;
# 分页显示
select * from emp limit 0,5; # 第一个参数表示起始位置,第二个参数表示的是条数,不是索引位置
select * from emp limit 5,5;
8.正则
# 在编程中,只要看到reg开头的,基本上都是跟正则相关
select * from emp where name regexp "^j.*(n|y)$";