数据库之查询语句

一、单表查询

 首先插入表,与数据开始正题:

#插入表
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
('jason','male',18,'20170301','张江第一帅形象代言',7300.33,401,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),
 
('歪歪','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)
;

1.语法执行顺序

#执行语句
select id,name from emp where id >= 3 and id <= 6;
#先后顺序
from
where
select

2.where 约束条件

#1.查询id大于等于3小于等于6的数据
select id,name from emp where id >= 3 and id <= 6;
select id,name from emp where id between 3 and 6;

#2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary = 20000 or salary = 18000 or salary = 17000;
select * from emp where salary in (20000,18000,17000);

#3.查询员工姓名中包含o字母的员工姓名和薪资
#在你刚开始接触mysql查询的时候,建议你按照查询的优先级拼写出你的sql语句
'''
解题思路:
    1.先是查哪张表 from emp;
    2.在根据什么条件去查 where name like '%o%'
    模糊匹配 like
        %:匹配多个任意字符
        _:匹配一个任意字符
    3.再是对查询出来的数据筛选展示部分 select name,salary
'''
select name,salary from emp where name like '%o%';

#4.查询员工姓名是由四个字符组成的员工姓名与其薪资
select name,salary from emp where name like '____';

#5.查询id小于3或者大于6的数据
select * from emp where id not between 3 and 6;

#6.查询薪资不在20000,18000,17000范围的数据
select * from emp where salary not in (17000,18000,20000);

#7.查询岗位描述为空的员工名和岗位名(针对null不能用等号,只能用is)
select name,post from emp where post_comment is null;

3.group by

#数据分组应用场景:每个部门的平均薪资,男女比例等

#1.按部门分组
select * from emp group by post; # 分组后取出的是每个组的第一条数据
select id,name,sex,post from emp group by post;

'''
设置sql_mode为only_full_group_by,意味着以后但凡分组,只能取到分组的依据,
不应该再取里面的单个元素的值,这样的话分组就没有意义了,因为不分组就是对单个元素信息的随意获取
'''
set global sql_mode='strict_trans_tables,only_full_group_by';

#重新连接客户端
select * from emp group by post; # 报错
select id,name,sex,post 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,count(id) from emp group by post;

#3.查询分组之后的部门名称和每个部门下所有的学生姓名
#group concat(分组之后用) 不仅可以用来显示除分组外字段还有拼接字符串的作用
select post,group_concat(name) from emp group by post;

select post,group_concat('nb',name) from emp group by post;

select post,group_concat(name,':',salary) from emp group by post;

#4.补充concat(不分组时用)拼接字符达到更好的显示效果 as语法使用
select concat('Name:',name) as 姓名,concat('Salary:',salary) as 薪资 from emp;

#补充as语法 即可以给字段起别名也可以表取别名
select t1.id,t1.name from emp as t1;

#查询四则运算
#查询每个人的年薪
select name,salary*12 as annual_salary from emp; #as 可以省略但是会显得语义不够清晰

练习题:

1. 查询岗位名以及岗位包含的所有员工名字
select post,group_concat(name) as 姓名 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;

'''
关键字where group by同时出现的情况下,group by必须在where之后
where先对整张表进行一次筛选,如何group by再对筛选过后的表进行分组
如何验证where是在group by之前执行而不是之后,利用聚合函数,因为聚合函数只能在分组之后才能使用
'''
select id,name,age from emp where max(salary) > 3000; #错误示范

select max(salary) from emp;
#正常运行,不分组意味着每一个人都是一组,等到运行max(salary)的时候已经经过where,group by操作了,只不过我们没有写这些条件而已

#语法顺序
select
from
where
group by

#执行顺序
from
where
group by
select

8.统计各部门年龄在30岁上的员工平均工资
select post,avg(salary) from emp where age > 30 group by post;

4.having

having的语法格式与where一致,只不过having是在分组之后进行的过滤,where虽然不能用聚合函数,但是having可以。

1.统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门
select post,avg(salary) from emp
    where age > 30
    group by post
    having avg(salary) > 10000;
# 强调:having必须在group by后面使用
select * from emp having avg(salary) > 10000; #会报错!

5.distinct

#对有重复的展示数据进行去重操作
select distinct age from emp;

6.order by

select * from emp order by salary asc; #默认升序排
select * from emp order by age desc; #降序排

#先按照年龄降序排,在年龄相同的情况下再按照薪资升序排
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

#限制展示条数
select * from emp limit 3;

#查询工资最高的人的详细信息
select * from emp order by salary desc limit 1;

#分页显示
select * from emp limit 0,5; #第一个参数表示起始位置,第二个参数表示的是条数
select * from emp iimit 5,5;

8.正则

select * from where name regexp '^j.*(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
('jason','male',18,200),
('egon','female',48,201),
('kevin','male',38,201),
('nick','female',28,202),
('owen','male',18,200),
('jerry','female',18,204)
;

1.表查询

select * from emp,dep; #左表数据与右表所有记录都对应一遍,我们称这种现象为笛卡尔积

#将所有的数据都对应了一遍,虽然不合理但是其中有合理的数据,现在我们需要做的就是找出合理的数据

#查询员工及所在部门的消息
select * from emp,dep where emp.dep_id = dep.id;

#查询部门为技术部的员工及部门信息
select * from emp,dep where emp.dep_id = dep.id and dep.name = '技术';

#将两张表关联到一起的操作,有专门对应的方法
1.内连接:只取两张表有对应关系的记录
select * from emp inner join dep on emp.dep_id = dep.id;

2.左连接:在内连接的基础上保留左表没有对应关系的记录
select * from emp left join dep on emp.dep_id = dep.id;

3.右连接:在内连接的基础上保留右表没有对应关系的记录
select * from emp right join dep on emp.dep_id = dep.id;

4.全连接:在内连接的基础上保留左、右面表没有对应关系的记录
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;

2.子查询

# 就是将一个查询语句的结果用括号括起来当做另外一个查询语句的条件去使用
# 1.查询部门是技术或者人力资源的员工信息
'''
先获取技术部和人力资源部的id号,再去员工表里面根据前面的id筛选出符合要求的员工信息
'''
select * from emp where dep_id in (select id from dep where name = '技术' or name = '人力资源');

#2.查看每个部门最新入职的员工
'''
解题思路:先查每个部门最新入职的员工,再按部门对应上联表查询
'''
select t1.id,t2.name,t1.post,t2.* from emp as t1
inner join
(select post,max(hire_date) from emp group by post) as t2
on t1.post = t2.post
where t1.hire_date = t2.max_date;
原文地址:https://www.cnblogs.com/spencerzhu/p/11391042.html