单表查询
前期表准备
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 emp\G; # 当表字段特别多的时候,结果的排版可能会出现混乱的现象,你可以在查询语句加\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)$";