MySQL----多表查询
多表关系
在进行数据库表结构的设计时,会根据业务的需求和业务模块之间的关系,分析设计表结构,由于业务之间相互关联,所以各个表结构之间也存在各种联系
表与表之间的联系:
1.一对多(多对一)
2.多对多
3.一对一
一对多(多对一)
例如,一个员工对应一个部门,一个部门可以对应多个员工
一般在多的一方创建外键,指向一的那一方
员工与部门,在员工表上设置外键,指向部门表
多对多
例如,一个学生可以选修多门课程,一个课程可以被多名学生选修
一般会建立第三张表,至少包含两个外键,分别指向两张表的主键
一对一
例如,用户和自己的学历信息的关系,一个人只对应一条学历信息
可以在任意一方加入外键,关联另一方的主键,并且设置外键为唯一(unique)
注:可以放在一张表中,但是对其进行拆分,一张表放基础信息,另一张表放详情,可以提升操作效率
多表查询
概述:
从多张表中查询数据
笛卡尔积:
笛卡尔积为两个集合(两张表)中的每条数据进行两两组合的结果
在多表查询时会产生笛卡尔积,要通过添加条件消除笛卡尔积
dept表:
emp表:
查询产生笛卡尔积的结果:
select*from emp, dept ;
消除笛卡尔积(添加条件):
select*from emp, dept where emp.dept_id=dept.id;
多表查询的分类
1.连接查询:
内连接:
相当于查询AB的交集部分
外连接:
左外连接:
查询A的所有数据,同时拼接上B对应的数据
右外连接:
查询B的所有数据,同时拼接上A中对应的数据
自连接:
表与自身连接查询
自连接必须给表取别名
2.子查询
数据准备
部门表:
createtable dept (
id intauto_incrementprimarykeycomment'id',
name varchar(50)notnullcomment'部门名称')comment'部门表';insertinto dept (id, name)values(1,'研发部'),(2,'市场部'),(3,'财务部'),(4,'销售部'),(5,'总经办'),(6,'人事部');
员工表:
createtable emp(
id intauto_incrementprimarykey,
name varchar(50)notnull,
age int,
job varchar(20)comment'职位',
salary int,
entrydate datecomment'入职时间',
managerid intcomment'直属领导id',
dept_id intcomment'所在部门id')comment'员工表';insertinto emp
values(1,'金庸',66,'总裁',20000,'2000-01-01',null,5),(2,'张无忌',20,'项目经理',12500,'2005-12-05',1,1),(3,'杨晓',33,'开发',8400,'2000-11-03',2,1),(4,'韦一笑',48,'开发',11000,'2002-02-05',2,1),(5,'陈玉存',43,'开发',10500,'2004-09-07',3,1),(6,'小昭',19,'程序员鼓励师',6600,'2004-10-12',2,1),(7,'灭绝',60,'财务总监',8500,'2002-09-12',1,3),(8,'周芷若',19,'会计',48000,'2006-06-02',7,3),(9,'丁敏君',23,'出纳',5250,'2009-05-13',7,3),(10,'赵敏',20,'市场部总监',12500,'2004-10-12',1,2),(11,'鹿杖客',56,'职员',3750,'2006-10-03',10,2),(12,'何碧文',19,'职员',3750,'2007-05-09',10,2),(13,'东方白',19,'职员',5500,'2009-02-12',10,2),(14,'张三丰',88,'销售总监',14000,'2004-10-12',1,4),(15,'鱼梁洲',38,'销售',4600,'2004-10-12',14,4),(16,'宋远桥',40,'销售',4600,'2004-10-12',14,4),(17,'陈友谅',42,null,2000,'2011-10-12',1,null);
内连接
语法:
# 隐式内连接select 字段列表 from 表1,表2where 条件;# 显示内连接select 字段列表 from 表1[inner]join 表2on 连接条件;
内连接查询的是两张表交集的部分
# 查询每一个员工的姓名及关联的部门的名称select emp.name, dept.name from emp, dept where emp.dept_id=dept.id;select emp.name, dept.name from emp innerjoin dept on emp.dept_id = dept.id;
外连接
语法:
# 左外连接select 字段列表 from 表1left[outer]join 表2on 条件;# 右外连接select 字段列表 from 表1right[outer]join 表2on 条件;
左外连接相当于查询表1的所有数据包含表1和表2交集的部分数据
右外连接相当于查询表2的所有数据包含表1和表2交集部分的数据
# 查询emp表的所有数据,和应于的部门信息(左)select emp.*, dept.*from emp leftouterjoin dept on emp.dept_id = dept.id;# 查询dept表的所有数据,和对于的员工信息(右)select dept.*, emp.*from emp rightouterjoin 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>5000unionallselect*from emp where age>50;
# 没有all重复满足条件的只出现一次# 将薪资低于5000的员工和年龄大于50的员工查询出来select*from emp where salary>5000unionselect*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查询员工信息# 先分开查询# 查询销售部门的idselect 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='销售部');
列子查询
子查询的结果为一列(可以是多行)的,这种子查询为列子查询
常用操作符:
# 列子查询# 查询销售部和市场部的所有员工信息# 查询销售部和市场部的idselect 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 leftouterjoin dept on e.dept_id=dept.id;
多表查询案例
数据准备:
createtable salgrade (
grade int,
losal intcomment'本薪资等级的最低界限',
hisal intcomment'最高界限')comment'薪资等级表';insertinto salgrade values(1,0,3000);insertinto salgrade values(2,3001,5000);insertinto salgrade values(3,5001,8000);insertinto salgrade values(4,8001,10000);insertinto salgrade values(5,10001,15000);insertinto salgrade values(6,15001,20000);insertinto salgrade values(7,20001,25000);insertinto 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
innerjoin dept d on e.dept_id = d.id
where e.age<30;
3.查询拥有员工的部门id,部门名称
selectdistinct d.id,d.name
from emp e, dept d
where d.id=e.dept_id;
4.查询所有年龄大于40的员工,及其归属部门名称,如果员工没有分配部门也要显示
select e.*,d.name
from emp e
leftouterjoin 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.查询研发部员工的平均工资
selectavg(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>(selectavg(e.salary)from emp e
);
10.查询低于本部门平均工资的员工信息
select*from emp
where emp.salary<(selectavg(salary)from emp e
where e.dept_id=emp.dept_id
);
11.查询所有部门信息,并统计部门的员工人数
select d.*,(selectcount(*)from emp
where emp.dept_id=d.id
)from dept d;
版权归原作者 萤火虫的小尾巴 所有, 如有侵权,请联系我们删除。