mysql数据语句执行顺序及多表查询
语句执行顺序
创建emp表,字段有id, name, sex, age, hire_data, post, post_comment, salary
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, # unsigned:非符号 hire_date date not null, post varchar(50), post_comment varchar(100), salary double(15,2), # 15位数字,两个小数 office int, #一个部门一个屋子 depart_id int );
往表中插入数据
#三个部门:教学,销售,运营 insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values ('bob','male',18,'20170301','teacher',7300.33,401,1), #以下是教学部 ('mac','male',78,'20150302','teacher',1000000.31,401,1), ('kevin','male',81,'20130305','teacher',8300,401,1), ('stv','male',73,'20140701','teacher',3500,401,1), ('office','male',28,'20121101','teacher',2100,401,1), ('jerry','female',18,'20110211','teacher',9000,401,1), ('tiny','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,'20101101','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), ('程咬银','female',18,'20130311','operation',19000,403,3), ('程咬铜','male',18,'20150411','operation',18000,403,3), ('程咬铁','female',18,'20140512','operation',17000,403,3) ;
一 where约束条件
执行顺序
from
where
select
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 salaary=20000 or salary=18000 or salary=17000 #第一种写法 select * from emp where salary in (20000,18000,17000) #第二种写法
3.查询员工姓名中包含o字母的员工姓名及薪资
select name, salary from emp where name like '%o%'; # like:模糊匹配,有两个语法. %:匹配多个任意字符 _:匹配一个任意字符
4.查询员工姓名是由四个字符组成的员工姓名与其薪资
select name, salary from emp where name like '____'; # 第一种写法 select name, salary from emp where char_length(name) = 4 #第二种写法
5.查询岗位描述为空的员工名与岗位名 注意:mysql中的空字段是用null表示的, 在查询null字段时, 不能使用=号,只能使用is, mysql对大小写不敏感
select name, post from emp where post_comment is null
二 group by
在我们所插入的数据中,数据分组的应用场景:每个部门的平均薪资,男女比例等
如何按照部门分组呢?
select * from emp group by post;
再次使用select id,name from emp group by post; 去查的时候会报错, 如果不报错,说明没有设置严格模式
设置sql_mode为only_full_group_by,意味着以后但凡分组,只能取到分组的依据,不应该在去取组里面的单个元素的值,那样的话分组就没有意义了,因为不分组就是对单个元素信息的随意获取
set global sql_mode="strict_trans_tables,only_full_group_by";
强调:只要分组了,就不能够再“直接”查找到单个数据信息了,只能获取到组名
首先我们要想一个问题, 既然分组之后我们不能够'直接'查找单个的数据信息了,那么我们如何去查看每个部门的最高薪资呢? 这个时候我们可以借助聚合函数去查.
聚合函数:
max:最大值
min:最小值
avg:平均值
sum:求和
count:计数
1.查看每个部门的最高薪资
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; # 这里我们可以使用任意非空字段去查,因为count是计数的操作,统计字段中数据出现了多少次,推荐使用id去查
group_concat(分组后使用):可以查看组内所有的数据,也可以进行拼接字符串操作
comcat(不分组时使用)
2. 查询分组之后的部门名称和每个部门下所有的学生姓名
select post, group_concat(name) from emp group by post;
在分组内的每个名字之前加上q字符
select post,group_concat('q', name) from emp group by post;
不分组时用
select concat('NAME:',name) as 姓名, concat('SALARY:',salary) as 薪资 from emp; #as 起别名
练习:
1. 查询岗位名以及岗位包含的所有员工名字
2. 查询岗位名以及各岗位内包含的员工个数
3. 查询公司内男员工和女员工的个数
4. 查询岗位名以及各岗位的平均薪资
5. 查询岗位名以及各岗位的最高薪资
6. 查询岗位名以及各岗位的最低薪资
7. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
答案参考
select post,group_concat(name) from emp group by post; select post,count(id) from emp group by post; select sex,count(id) from employee group by sex; select post,avg(salary) from emp group by post; select post,max(salary) from employee group by post; select post,min(salary) from employee group by post; select sex,avg(salary) from employee group by sex;
8.统计个部门年龄在30以上的员工平均工资
这里涉及到一个执行顺序
from
where
group by
select
select post,avg(salary) from emp where age>30 group by post;
三 having
跟where是一模一样的,也是用来筛选数据,但是having是跟在group by之后的,where是对整体数据做一个初步的筛选,而having是对分组之后的数据再进行一次针对性的筛选
1.统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门
执行顺序
from
where
group by
having
select
select post,avg(salary) from emp where age > 30 group by post having avg(salary)>10000;
四 distinct去重
去重必须数据是一模一样的才能去重,只要有一个不一样 都不能算是的重复的数据
select distinct id, age from emp; # 这样写达不到去重的效果,只有一模一样的才能去重
select distinct age from emp; # 达到去重效果
五 order by
order by:排序, 默认是升序(asc),如果要调整成降序,要使用关键字desc
select * from emp order by salary; #对salary进行排序,默认升序
select * from emp order by salary desc; # 使用降序进行排序
统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资进行排序(降序)
select post,avg(salary) from emp where age > 10 group by post having avg(salary) > 1000 order by avg(salary) desc;
六 limit
limit:限制展示数据的条数
当limit只有一个参数的时候 表示的是只展示几条
select * from emp limit 5;
当limit有两个参数的时候 第一个参数表示的起始位置 第二个参数表示从起始位置开始往后展示的条数
select * from emp limit 5, 10;
查询工资最高的人的详细信息
思路:先根据薪资按照降序排序,第一条就是薪资最高的那个人,使用limit拿到1条数据
select * from emp order by salary desc limit 1;
七 正则
select * from emp where name regexp '^j.*(n|y)$'; 正则解释: ^j,以j开头 .*,匹配0到多个字符 (n|y)$,以n或者y结尾
多表查询
创建两张表
create table dep( id int, name varchar(20) ); create table emp( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male', age int, dep_id int );
插入数据
insert into dep values (200,'技术'), (201,'人力资源'), (202,'销售'), (203,'运营'); insert into emp(name,sex,age,dep_id) values ('json','male',18,200), ('exit','female',48,201), ('kevin','male',38,201), ('nick','female',28,202), ('bob','male',18,200), ('jerry','female',18,204) ;
如下图所示:
如何查询json属于哪个部门呢? 我们先来推导一下
select * from emp,dep;
这样查出来的数据明显不是我们想要的,冗余的数据过多,把每一个部门都显示了一遍
那我们只显示相同的id结果会如何呢?
select * from emp,dep where emp.dep_id = dep.id
这种联表查询太麻烦了
多表查询的方式
内连接(inner join): 只去两张表有对应关系的记录
select * from emp inner join dep on emp.dep_id = dep.id; # on后面跟的是查询条件
左连接(left join): 在内连接的基础上保留左表没有对应关系的记录
select * from emp left join dep on emp.dep_id = dep.id;
右连接(right join): 在内连接的基础上保留右表没有对应关系的记录
select * from emp right join dep on emp.dep_id = emp.id;
全连接(union): 在内连接的基础上保留左,右表没有对应关系的记录
select * from emp left join dep on emp.dep_id = dep.id union select * from emp right join dep on emp.dep_id = dep.id;
子查询
就是将一个查询语句的结果用括号括起来当作另外一个查询语句的条件去用
查询部门是技术或者人力资源的员工信息
select * from emp where dep_id in (select id from dep where name = "技术" or name = "人力资源"); # 括号内就是另一张表的查询结果,当做了另一张表的查询条件