MySQL表的高级查询

本章节重点

多表连接
符合条件连接查询
子查询

准备工作:准备两张表,部门表(department)、员工表(employee)

create table department(
id int,
name varchar(20)
);
create table employee(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

插入数据

insert into department values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营');
insert into employee(name,sex,age,dep_id) values
('egon','male',18,200),
('alex','female',48,201),
('wupeiqi','male',38,201),
('yuanhao','female',28,202),
('nvshen','male',18,200),
('xiaomage','female',18,204)
;

查看表的结构和数据

在这里插入图片描述

一、多表连接查询

重点:外连接语法
语法:

SELECT 字段列表
 FROM1 INNER|LEFT|RIGHT JOIN2
 ON1.字段 =2.字段;

(1)先看第一种情况交叉连接:不适用任何匹配条件。生成笛卡尔积

select * from employee,department;

在这里插入图片描述

(2)内连接:自连接匹配的行

#找两张表共有的部分,相当于利用条件从笛卡尔积结果中筛选出了匹配的结果
#department 没有 204 这个部门,因而 employee 表中关于 204 这条员工信息没有匹配出来
select
employee.id,employee.name,employee.age,employee.sex,department.name
from employee inner join department on employee.dep_id=department.id;

在这里插入图片描述

(3)外链接之左连接:优先显示左表全部记录

#以左表为准,即找出所有员工信息,当然包括没有部门的员工
#本质就是:在内连接的基础上增加左边有,右边没有的结果
select employee.id,employee.name,department.name as
depart_name from employee left join department on
employee.dep_id=department.id;

在这里插入图片描述

(4) 外链接之右连接:优先显示右表全部记录

#以右表为准,即找出所有部门信息,包括没有员工的部门
#本质就是:在内连接的基础上增加右边有,左边没有的结果
select employee.id,employee.name,department.name as
depart_name from employee right join department on
employee.dep_id=department.id;

在这里插入图片描述

(5) 全外连接:显示左右两个表全部记录(了解)

#外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
#注意:mysql 不支持全外连接 full JOIN
#强调:mysql 可以使用此种方式间接实现全外连接
语法:select * from employee left join department on employee.dep_id
= department.id
 union all
select * from employee right join department on employee.dep_id
= department.id;

select * from employee left join department on
employee.dep_id = department.id
 union
select * from employee right join department on
employee.dep_id = department.id
#注意 union与union all 的区别:union会去掉相同的记录

在这里插入图片描述

二、符合条件连接查询

示例 1:以内连接的方式查询 employee 和 department 表,并且 employee 表中的 age 字段值必须大于 25,即找出年龄大于 25 岁的员工以及员工所在的部门

select employee.name,department.name from employee inner joindepartment
on employee.dep_id = department.id
where age > 25;

示例 2:以内连接的方式查询 employee 和 department 表,并且以 age 字段的升序方式显示。

select employee.id,employee.name,employee.age,department.name from
employee,department
where employee.dep_id = department.id
and age > 25
order by age asc;

三、子查询

#1:子查询是将一个查询语句嵌套在另一个查询语句中。
#2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
#3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS 等关
键字
#4:还可以包含比较运算符:= 、 !=、> 、<等

例子:
(1)带in关键字的子查询

#查询平均年龄在 25 岁以上的部门名
select id,name from department
where id in
(select dep_id from employee group by dep_id having
avg(age) > 25);

# 查看技术部员工姓名
select name from employee
where dep_id in
(select id from department where name='技术');

#查看不足 1 人的部门名
select name from department
where id not in
(select dep_id from employee group by dep_id);

(2)带比较运算符的子查询

#比较运算符:=、!=、>、>=、<、<=、<>
#查询大于所有人平均年龄的员工名与年龄
select name,age from employee where age > (select avg(age)
from employee);

#查询大于部门内平均年龄的员工名、年龄
思路:
(1)先对员工表(employee)中的人员分组(group by),查询出 dep_id
以及平均年龄。
(2)将查出的结果作为临时表,再对根据临时表的 dep_id 和 employee 的
dep_id 作为筛选条件将 employee 表和临时表进行内连接。
(3)最后再将 employee 员工的年龄是大于平均年龄的员工名字和年龄筛
选。

select t1.name,t1.age from employee as t1
inner join
(select dep_id,avg(age) as avg_age from employee group by
dep_id) as t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age;

(3)带 EXISTS 关键字的子查询

#EXISTS 关字键字表示存在。在使用 EXISTS 关键字时,内层查询语句不返回查
询的记录。而是返回一个真假值。True 或 False
#当返回 True 时,外层查询语句将进行查询;当返回值为 False 时,外层查询
语句不进行查询
#department 表中存在 dept_id=203,Ture

select * from employee where exists (select id from
department where id=200);

在这里插入图片描述

#department 表中存在 dept_id=205,False
select * from employee where exists (select id from
department where id=204);
Empty set (0.00 sec)

小练习:
查询每个部门最新入职的那位员工

#创建表
create table employee(
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
employee(name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','江西软件职业大学',7300.33,401,1), #以下是教学部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龙','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)
;

#答案1
select * from employee as t1
inner join
(select post,max(hire_date) as new_date from employee group by post)
as t2
on t1.post=t2.post
where t1.hire_date=t2.new_date;

#答案2
select * from employee where hire_date in(
select max(hire_date) from employee group by post);

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡陌熙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值