外连接
语法:
# 左外连接 select 字段列表 from 表1 left [outer] join 表2 on 条件; # 右外连接 select 字段列表 from 表1 right [outer] join 表2 on 条件;
左外连接相当于查询表1的所有数据包含表1和表2交集的部分数据
右外连接相当于查询表2的所有数据包含表1和表2交集部分的数据
# 查询emp表的所有数据,和应于的部门信息(左) select emp.*, dept.* from emp left outer join dept on emp.dept_id = dept.id; # 查询dept表的所有数据,和对于的员工信息(右) select dept.*, emp.* from emp right outer join dept on emp.dept_id = dept.id;
左外连接和右外连接可以进行相互转化
自连接
语法:
select 字段列表 from 表a 别名a join 表a 别名b on 条件;
自链接查询可以是内连接查询也可以是外连接查询
# 查询员工及其所属领导的名字 # 自连接可以看成两张一样的表进行连接查询 select a.name, b.name from emp a join emp b on a.managerid=b.id;
联合查询
union、union all
对于联合查询就是把多次查询的结果合并起来,形成一个新的查询结果集
语法:
select 字段列表 from 表a union [all] select 字段列表 from 表b
# 将薪资低于5000的员工和年龄大于50的员工查询出来 select * from emp where salary>5000 union all select * from emp where age>50;
# 没有all重复满足条件的只出现一次 # 将薪资低于5000的员工和年龄大于50的员工查询出来 select * from emp where salary>5000 union select * from emp where age>50;
对于联合查询的多张表的列数必须保持一致,字段类型也要保持一致
union all会将全部的数据直接合并在一起,union会对合并之后的数据去重
子查询
概念:SQL语句中嵌套select语句为嵌套查询,又称子查询
select * from 表1 where 字段=(select 字段 from 表2);
子查询外的语句可以是insert、update、delete、select中的一个
根据子查询的结构不同,分为:
标量子查询:子查询的结果为单个值 列子查询:子查询的结果为一列 行子查询:子查询的结果为一行 表子查询:子查询的结果为多行多列
根据子查询的位置,分为:
where之后 from之后 select之后
标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询
常用符号:=、<>、>、>=、<、<=
# 根据销售部门的id查询员工信息 # 先分开查询 # 查询销售部门的id select id from dept where name='销售部'; #id为4 # 查询销售部门中员工的信息 select * from emp where dept_id=4; # 合并为一个查询 select * from emp where dept_id=(select dept.id from dept where dept.name='销售部' );
列子查询
子查询的结果为一列(可以是多行)的,这种子查询为列子查询
常用操作符:
# 列子查询 # 查询销售部和市场部的所有员工信息 # 查询销售部和市场部的id select id from dept where name='销售部' or name='市场部'; #id为2 4 # 查询两个部门的所有员工 select * from emp where dept_id in (2,4); # 合并 select * from emp where dept_id in (select id from dept where name='销售部' or name='市场部');
行子查询
子查询返回的结果是一行(可以是多列),这种子查询为行子查询
常用操作符:=、<>、in、not in
# 查询与张无忌的薪资及直属领导相同的员工信息 # 查询张无忌的薪资和直属领导 select salary, managerid from emp where name='张无忌'; # 查询与张无忌的薪资及直属领导相同的员工信息 select * from emp where (salary,managerid)=(select salary, managerid from emp where name='张无忌');
表子查询
子查询的结果是多行多列这种查询为表子查询
常用操作符:in
# 查询与鹿杖客和宋远桥的职位和薪资相同的员工信息 select * from emp where (job, salary) in ( select job, salary from emp where name in ('鹿杖客', '宋远桥'));
表子查询的子表作为临时表
# 查询入职日期是’2006-01-01‘之后的员工信息和部门信息 # 先查询出入职在’2006-01-01‘之后员工的所有信息 # 与部门表左连接 select e.*, dept.* from (select * from emp where entrydate>'2006-01-01') e left outer join dept on e.dept_id=dept.id;
多表查询案例
数据准备:
create table salgrade ( grade int, losal int comment '本薪资等级的最低界限', hisal int comment '最高界限' ) comment '薪资等级表'; insert into salgrade values (1,0,3000); insert into salgrade values (2,3001,5000); insert into salgrade values (3,5001,8000); insert into salgrade values (4,8001,10000); insert into salgrade values (5,10001,15000); insert into salgrade values (6,15001,20000); insert into salgrade values (7,20001,25000); insert into salgrade values (8,025001,30000);
1.查询员工的姓名,年龄,职位,部门信息(隐式内连接)
select e.name, e.age, e.job, d.* from emp e, dept d where e.dept_id=d.id;
2.查询年龄小于30的员工的姓名、年龄、职位、部门信息(显示内连接)
select e.name,e.age,e.job,d.* from emp e inner join dept d on e.dept_id = d.id where e.age<30;
3.查询拥有员工的部门id,部门名称
select distinct d.id,d.name from emp e, dept d where d.id=e.dept_id;
4.查询所有年龄大于40的员工,及其归属部门名称,如果员工没有分配部门也要显示
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id where e.age>40;
5.查询所有员工的工资等级
select e.*,s.grade from emp e, salgrade s where e.salary between s.losal and s.hisal;
6.查询研发部所有员工的信息即工资等级
select e.*,s.grade from emp e,dept d,salgrade s where (e.dept_id=d.id) and (d.name='研发部') and (e.salary between s.losal and s.hisal);
7.查询研发部员工的平均工资
select avg(e.salary) from emp e, dept d where e.dept_id=d.id and d.name='研发部';
8.查询工资比灭绝高的员工信息
select * from emp where emp.salary > ( select e.salary from emp e where e.name='灭绝' );
9.查询比平均薪资高的员工信息
select * from emp where salary> ( select avg(e.salary) from emp e );
10.查询低于本部门平均工资的员工信息
select * from emp where emp.salary<( select avg(salary) from emp e where e.dept_id=emp.dept_id );
11.查询所有部门信息,并统计部门的员工人数
select d.*, ( select count(*) from emp where emp.dept_id=d.id ) from dept d;