多表查询
分类:内链接查询、外链接查询、子查询
1. 内连接查询:查询表的交集部分
注意要确定的内容:要从那些表里面查询、查询的条件是什么、要查询那些字段
-
隐式内连接:使用where条件来消除无用数据
SELECT t1.NAME, -- 员工表的姓名 t1.gender, -- 员工表的性别 t2.NAME -- 部门表的名字 FROM emp t1, -- 员工表 dept t2 -- 部门表 WHERE t1.dept_id = t2.id;-- dept-id是员工表的外键,与部门表的ID关联
-
显示内连接:
-
语法:
select 字段列表 from 表名1 [inner] join 表名2 on 条件
SELECT t1.NAME, -- 员工表的姓名 t1.gender, -- 员工表的性别 t2.NAME -- 部门表的名字 FROM emp t1 -- 员工表 JOIN dept t2 ON t1.dept_id = t2.id;
-
2. 外连接查询
-
左外连接:
-
语法:
select 字段列表 from 表1 left [outer] join 表2 on 条件
-
解释:查询的结果是查询左表的所有数据,以及两个表的交集部分
SELECT t1.*, t2.NAME FROM emp t1 LEFT JOIN dept t2 ON t1.dept_id = t2.id;
-
-
右外连接语法与左外一样,是一个先对的概念,left --> right
SELECT t1.*, t2.NAME FROM emp t1 RIGHT JOIN dept t2 ON t1.dept_id = t2.id;
3. 子查询
概念:查询中嵌套查询,称嵌套查询为子查询
子查询的情况:
-
子查询的结果是单行单列的
-
子查询可以作为条件,使用运算符>, <, = , != 进行判断
SELECT * from emp where salary < (SELECT avg(salary) FROM emp);
-
-
子查询的结果是多行单列的
-
子查询可以作为条件,使用IN进行判断(事实上子查询结果是一个集合)
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME IN ('财务部', '市场部'));-- 结果是多行单列的
-
-
子查询的结果是多行多列的
- 子查询的结果可以作为一张虚拟表,参与查询操作
4.练习
现在有4张表,如下图
-
emp表有两个外键:一个是和job表关联的job_id,另一个是和dept表关联的dept_id
-
salarygrade表没有和其他表与关联关系
-- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述 /* 分析:员工编号,员工姓名,工资可以在员工表emp里查询到 职务名称,职务描述可以在job表里查询到 条件:使用emp.job_ib = job.id */ SELECT t1.id, -- 员工编号 t1.ename, -- 员工姓名 t1.salary, -- 员工工资 t2.jname, -- 职务名称 t2.description -- 职务描述 FROM emp t1, job t2 WHERE t1.job_id = t2.id; -- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置 /* 分析:三张表的查询: 员工编号,员工姓名,工资可以在员工表emp里查询到 职务名称,职务描述可以在job表里查询到 部门名称,部门位置可以在dept表查询到 条件:使用emp.job_ib = job.id AND emp.dept_id = dept.id */ SELECT t1.id, -- 员工编号 t1.ename, -- 员工姓名 t1.salary, -- 员工工资 t2.jname, -- 职务名称 t2.description, -- 职务描述 t3.dname, t3.loc FROM emp t1, job t2, dept t3 WHERE t1.job_id = t2.id AND t1.dept_id = t3.id; -- 3.查询员工姓名,工资,工资等级 /* 分析:员工姓名、工资:emp表 工资等级:salarygrade表 条件:emp.salary between salarygrade.losalary and hisalary; */ SELECT t1.ename, t1.salary, t2.grade FROM emp t1, salarygrade t2 WHERE t1.salary BETWEEN t2.losalary AND t2.hisalary; -- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级 /* 分析:四张表 员工姓名,工资:emp表 职务名称,职务描述:job表 部门名称,部门位置:dept表 工资等级:salarygrade表 条件:emp. */ SELECT t1.ename, t1.salary, t2.jname, t2.description, t3.dname, t3.loc, t4.grade FROM emp t1, job t2, dept t3, salarygrade t4 WHERE t1.dept_id = t3.id AND t1.job_id = t2.id AND t1.salary BETWEEN t4.losalary AND t4.hisalary; -- 5.查询出部门编号、部门名称、部门位置、部门人数 SELECT t1.id, t1.dname, t1.loc, total FROM dept t1, (SELECT dept_id, count(id) total FROM emp GROUP BY dept_id) t2 WHERE t1.id = t2.dept_id; SELECT dept_id, count(id) FROM emp GROUP BY dept_id; -- 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询 /* 分析:员工姓名:emp,上级姓名:emp 1. 这是一个自关联的 2. 条件:emp.id = emp.mgr 3. 没有上级也要查询出来,也就是左表的全部信息,以及交集部分 */ SELECT t1.ename, t1.mgr, t2.id, t2.ename FROM emp t1 -- 一张表,两个别名 LEFT JOIN emp t2 ON t1.mgr = t2.id;