多表查询
1.基本查询语法
select 列表名称 from 表名列表 where 条件
- 准备笔记
-- 部门信息表
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
);
-- 员工信息表
CREATE TABLE emp(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
sex CHAR(2),
salary DOUBLE ,
join_date DATE,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES dept(id)
);
数据信息:
emp表数据
dept表数据
2.笛卡尔积:
* 有两个集合A,B,取这两个集合的所有组成情况。
emp表有5条数据,dept表有3条数据,使用笛卡尔积查询会有15条数据,
存在重复无用的数据
- 实例表现
3.多表查询
-
1.内连接查询:
1.隐式内连接: * 语法:使用where条件消除无用数据 * 例子 -- 查询所有员工信息和对应的部门信息
SELECT * FROM emp,dept WHERE emp.dept_id = dept.id ;
结果如图(消除了刚才重复的数据)
2.显式内连接:
* 语法:select 字段列表 from 表名1 [inner] join 表名2 on 条件;
* 关键字:[inner] join on 【inner可以省略不写】
* 例如
-- 查询所有员工信息和对应的部门信息
SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id;
SELECT * FROM emp JOIN dept ON emp.dept_id = dept.id;
结果如上图(只是换了一种方法)
注意事项:
1.从哪些表查询数据
2.查询的条件是什么
3.查询哪些字段
-
2.外连接查询:
例子:先在emp表添加小白龙数据,但是不添加部门信息
-- 查询所有员工信息,如果员工有部门,则查询部门名称,如果没部门,则不显示部门名称
SELECT
t1.*,t2.name
FROM
emp t1,dept t2
WHERE
t1.dept_id = t2.id;
结果如图:没有小白龙数据
注意:使用左外连接或右外连接可以解决
1.左外连接
* 语法: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;
结果如图:小白龙出现
2.右外连接
* 语法:select 字段列表 from 表名1 right [outer] join 表名2 on 条件;
* 查询的是右表所有数据以及与右表交集部分(条件)
SELECT
t1.*,t2.name
FROM
emp t1 RIGHT JOIN dept t2
ON
t1.dept_id = t2.id;
-
3.子查询:
* 概念:查询中嵌套查询,称嵌套查询是子查询。
-
子查询不同情况
1.子查询的情况是单行单列的 * 子查询可以作为条件,使用运算符去判断的
-
– 查询员工工资小于平均工资的人
-- 1.查询最高工资是多少 9000
SELECT MAX(salary) FROM emp;
-- 2.查询员工信息,并且工资等于9000
SELECT * FROM emp WHERE salary = 9000;
-- 一条sql语句完成操作(合并上面两条语句)
SELECT * FROM emp WHERE emp.salary = (SELECT MAX(salary) FROM emp);
结果如图:
2.子查询的情况是多行单列的
* 子查询可以作为条件,使用运算符in 作为条件
– 查询财务部和市场部的员工信息
-- 1.普通查询财务部和市场部的员工信息
SELECT id FROM dept WHERE NAME= '财务部' OR NAME= '市场部';
SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
SELECT * FROM emp WHERE dept_id IN (3,2);
-- 子查询
SELECT
*
FROM
emp
WHERE
dept_id IN (SELECT id
FROM dept
WHERE NAME= '财务部' OR NAME= '市场部'
);
结果如图:
3.子查询的情况是多行多列的
* 子查询可以作为一张虚拟表
– 查询员工入职日期是2013-5-10日之后的员工信息和部门信息
分析:
1.先查询入职日期是2013-5-10日之后的员工信息
SELECT * FROM emp WHERE join_date > '2013-05-10';
结果如图:
2.再将结果作为一张虚拟表
SELECT
*
FROM
dept t1 ,(SELECT * FROM emp WHERE join_date > '2013-05-10') t2
WHERE
t1.id = t2.dept_id;
结果如图:
4.多表查询实例练习
- 准备工作
创建以下表(以下所有的代码使用了 别名 )
-- 部门表
CREATE TABLE dept (
id INT NOT NULL,
dname VARCHAR(50) DEFAULT NULL,
loc VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (id)
)
-- 员工表
CREATE TABLE emp (
id INT PRIMARY KEY, -- 员工id
ename VARCHAR(20), -- 员工姓名
job_id INT, -- 职务id
mgr INT, -- 上级领导
joindate DATE , -- 入职日期
salary DECIMAL(7,2), -- 工资
bonus DECIMAL(7,2), -- 奖金
dept_id INT, -- 所在部门编号
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);
-- 职务表
CREATE TABLE `job` (
`id` INT NOT NULL,
`jname` VARCHAR(20) DEFAULT NULL,
`description` VARCHAR(50) DEFAULT NULL,
PRIMARY KEY (`id`)
)
-- 工资等级表
CREATE TABLE salarygrade(
grade INT PRIMARY KEY,
losalary INT,
hisalary INT
);
-
练习1
1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述 分析: 1.查询员工编号,员工姓名,工资 emp表 , 职务名称,职务描述 job表 2.查询条件:t1.job_id = t2.id
SELECT
t1.id, -- 员工编号
t1.ename, -- 员工姓名
t1.salary, -- 工资
t2.jname, -- 职务名称
t2.description -- 职务描述
FROM
emp t1 , job t2
WHERE
t1.job_id = t2.id
-
练习2
2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置 分析: 1.员工编号,员工姓名,工资 emp表 职务名称,职务描述 job表 部门名称,部门位置 dept表 2.查询条件 t1.job_id = t2.id and t1.dept_id = t3.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
3.查询员工姓名,工资,工资等级。 分析: 1.员工姓名,工资,emp表 工资等级 salarygrade表 2.查询条件:emp.salary>=losalary and emp.salary<=hisalary 或emp.salary between 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
4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级 分析: 1.员工姓名,工资 emp表 , 职务名称,职务描述,job表 , 部门名称,部门位置 dept表 ,工资等级 salarygrade表 2.查询条件:
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.job_id = t2.id AND t1.dept_id = t3.id AND t1.salary BETWEEN t4.losalary AND t4.hisalary;
-
练习5
5.查询部门编号,部门名称,部门位置,部门人数 分析: 1.部门编号,部门名称,部门位置 dept 表 部门人数 emp表 2.使用分组查询,把dept_id分组,count(id),形成虚拟表 3.使用子查询,虚拟表
-- 虚拟表
SELECT
dept_id,COUNT(id)
FROM
emp
GROUP BY dept_id;
SELECT
t1.id,t1.dname,t1.loc,t2.tatol
FROM
dept t1,(SELECT dept_id,COUNT(id) tatol
FROM emp
GROUP BY dept_id) t2
WHERE t1.id = t2.dept_id;
-
练习6(难理解)
6.查询所有员工的姓名及其直接上级名称,没有领导的员工也需要查询 分析: 1.姓名 emp表 ,直接上级名称 emp表 注意 * emp表的id和mgr是自关联的 2.条件 emp.id等于emp.mgr 3.查询右表的所有数据和交集数据,使用左外连接
SELECT
t1.ename, -- 员工姓名
t1.id, -- 员工id
t2.ename -- 员工的上级领导姓名
FROM emp t1
LEFT JOIN emp t2
ON t1.mgr = t2.id ;
图形理解