MySQL高级【多表查询】第九章

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 多表查询:内连接,外连接,子查询,案例

1,多表查询

多表查询顾名思义就是从多张表中一次性的查询出我们想要的数据。我们通过具体的sql给他们演示,先准备环境


DROP TABLE IF EXISTS emp;

DROP TABLE IF EXISTS dept;

# 创建部门表

CREATE TABLE dept(

       did INT PRIMARY KEY AUTO_INCREMENT,

       dname VARCHAR(20)

   );

# 创建员工表

CREATE TABLE emp (

       id INT PRIMARY KEY AUTO_INCREMENT,

       NAME VARCHAR(10),

       gender CHAR(1), -- 性别

       salary DOUBLE, -- 工资

       join_date DATE, -- 入职日期

       dep_id INT,

       FOREIGN KEY (dep_id) REFERENCES dept(did) -- 外键,关联部门表(部门表的主键)

   );

-- 添加部门数据

INSERT INTO dept (dNAME) VALUES ('研发部'),('市场部'),('财务部'),('销售部');

-- 添加员工数据

INSERT INTO emp(NAME,gender,salary,join_date,dep_id) VALUES

('孙悟空','男',7200,'2013-02-24',1),

('猪八戒','男',3600,'2010-12-02',2),

('唐僧','男',9000,'2008-08-08',2),

('白骨精','女',5000,'2015-10-07',3),

('蜘蛛精','女',4500,'2011-03-14',1),

('小白龙','男',2500,'2011-02-14',null);


执行下面的多表查询语句  


select * from emp , dept;  -- 从emp和dept表中查询所有的字段数据

结果如下:  


从上面的结果我们看到有一些无效的数据,如 孙悟空 这个员工属于1号部门,但也同时关联的2、3、4号部门。所以我们要通过限制员工表中的 dep_id 字段的值和部门表 did 字段的值相等来消除这些无效的数据,


select * from emp , dept where emp.dep_id = dept.did;

执行后结果如下:




上面语句就是连接查询,那么多表查询都有哪些呢?


连接查询


内连接查询 :相当于查询AB交集数据


外连接查询


左外连接查询 :相当于查询A表所有数据和交集部门数据


右外连接查询 : 相当于查询B表所有数据和交集部分数据


子查询  


1.1:内连接查询

语法


-- 隐式内连接

SELECT 字段列表 FROM 表1,表2… WHERE 条件;

-- 显示内连接

SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 条件;

内连接相当于查询 A B 交集数据




案例


隐式内连接


SELECT

*

FROM

emp,

dept

WHERE

emp.dep_id = dept.did;

执行上述语句结果如下:  


查询 emp的 name, gender,dept表的dname


SELECT

emp. NAME,

emp.gender,

dept.dname

FROM

emp,

dept

WHERE

emp.dep_id = dept.did;

执行语句结果如下:




上面语句中使用表名指定字段所属有点麻烦,sql也支持给表指别名,上述语句可以改进为


SELECT

t1. NAME,

t1.gender,

t2.dname

FROM

emp t1,

dept t2

WHERE

t1.dep_id = t2.did;

显式内连接


select * from emp inner join dept on emp.dep_id = dept.did;-- 上面语句中的inner可以省略,可以书写为如下语句select * from emp  join dept on emp.dep_id = dept.did;



1.2:外连接查询

语法


-- 左外连接

SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件;

-- 右外连接

SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 条件;

左外连接:相当于查询A表所有数据和交集部分数据


右外连接:相当于查询B表所有数据和交集部分数据




案例


查询emp表所有数据和对应的部门信息(左外连接)


select * from emp left join dept on emp.dep_id = dept.did;

执行语句结果如下:




结果显示查询到了左表(emp)中所有的数据及两张表能关联的数据。


查询dept表所有数据和对应的员工信息(右外连接)


select * from emp right join dept on emp.dep_id = dept.did;

执行语句结果如下:




结果显示查询到了右表(dept)中所有的数据及两张表能关联的数据。


要查询出部门表中所有的数据,也可以通过左外连接实现,只需要将两个表的位置进行互换


select * from dept left join emp on emp.dep_id = dept.did;

1.3:子查询

概念


==查询中嵌套查询,称嵌套查询为子查询。==


什么是查询中嵌套查询呢?我们通过一个例子来看:


需求:查询工资高于猪八戒的员工信息。


来实现这个需求,我们就可以通过二步实现,第一步:先查询出来 猪八戒的工资


select salary from emp where name = '猪八戒'

第二步:查询工资高于猪八戒的员工信息


select * from emp where salary > 3600;

第二步中的3600可以通过第一步的sql查询出来,所以将3600用第一步的sql语句进行替换


select * from emp where salary > (select salary from emp where name = '猪八戒');

这就是查询语句中嵌套查询语句。


子查询根据查询结果不同,作用不同


子查询语句结果是单行单列,子查询语句作为条件值,使用 = != > < 等进行条件判断


子查询语句结果是多行单列,子查询语句作为条件值,使用 in 等关键字进行条件判断


子查询语句结果是多行多列,子查询语句作为虚拟表


案例


查询 '财务部' 和 '市场部' 所有的员工信息


-- 查询 '财务部' 或者 '市场部' 所有的员工的部门did

select did from dept where dname = '财务部' or dname = '市场部';

select * from emp where dep_id in (select did from dept where dname = '财务部' or dname = '市场部');

查询入职日期是 '2011-11-11' 之后的员工信息和部门信息


-- 查询入职日期是 '2011-11-11' 之后的员工信息

select * from emp where join_date > '2011-11-11' ;

-- 将上面语句的结果作为虚拟表和dept表进行内连接查询

select * from (select * from emp where join_date > '2011-11-11' ) t1, dept where t1.dep_id = dept.did;

1.4:案例

环境准备:


DROP TABLE IF EXISTS emp;

DROP TABLE IF EXISTS dept;

DROP TABLE IF EXISTS job;

DROP TABLE IF EXISTS salarygrade;

-- 部门表

CREATE TABLE dept (

 did INT PRIMARY KEY PRIMARY KEY, -- 部门id

 dname VARCHAR(50), -- 部门名称

 loc VARCHAR(50) -- 部门所在地

);

-- 职务表,职务名称,职务描述

CREATE TABLE job (

 id INT PRIMARY KEY,

 jname VARCHAR(20),

 description VARCHAR(50)

);

-- 员工表

CREATE TABLE emp (

 id INT PRIMARY KEY, -- 员工id

 ename VARCHAR(50), -- 员工姓名

 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 salarygrade (

 grade INT PRIMARY KEY,   -- 级别

 losalary INT,  -- 最低工资

 hisalary INT -- 最高工资

);

 

-- 添加4个部门

INSERT INTO dept(did,dname,loc) VALUES

(10,'教研部','北京'),

(20,'学工部','上海'),

(30,'销售部','广州'),

(40,'财务部','深圳');

-- 添加4个职务

INSERT INTO job (id, jname, description) VALUES

(1, '董事长', '管理整个公司,接单'),

(2, '经理', '管理部门员工'),

(3, '销售员', '向客人推销产品'),

(4, '文员', '使用办公软件');

-- 添加员工

INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES

(1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),

(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),

(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),

(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),

(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),

(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),

(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),

(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),

(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),

(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),

(1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),

(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),

(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),

(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);

-- 添加5个工资等级

INSERT INTO salarygrade(grade,losalary,hisalary) VALUES

(1,7000,12000),

(2,12010,14000),

(3,14010,20000),

(4,20010,30000),

(5,30010,99990);


需求


查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述


/*

分析:

 1. 员工编号,员工姓名,工资 信息在emp 员工表中

 2. 职务名称,职务描述 信息在 job 职务表中

 3. job 职务表 和 emp 员工表 是 一对多的关系 emp.job_id = job.id

*/

-- 方式一 :隐式内连接

SELECT

emp.id,

emp.ename,

emp.salary,

job.jname,

job.description

FROM

emp,

job

WHERE

emp.job_id = job.id;

-- 方式二 :显式内连接

SELECT

emp.id,

emp.ename,

emp.salary,

job.jname,

job.description

FROM

emp

INNER JOIN job ON emp.job_id = job.id;


查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置


/*

分析:

 1. 员工编号,员工姓名,工资 信息在emp 员工表中

 2. 职务名称,职务描述 信息在 job 职务表中

 3. job 职务表 和 emp 员工表 是 一对多的关系 emp.job_id = job.id

 4. 部门名称,部门位置 来自于 部门表 dept

 5. dept 和 emp 一对多关系 dept.id = emp.dept_id

*/

-- 方式一 :隐式内连接

SELECT

emp.id,

emp.ename,

emp.salary,

job.jname,

job.description,

dept.dname,

dept.loc

FROM

emp,

job,

dept

WHERE

emp.job_id = job.id

and dept.id = emp.dept_id

;

-- 方式二 :显式内连接

SELECT

emp.id,

emp.ename,

emp.salary,

job.jname,

job.description,

dept.dname,

dept.loc

FROM

emp

INNER JOIN job ON emp.job_id = job.id

INNER JOIN dept ON dept.id = emp.dept_id


查询员工姓名,工资,工资等级


SELECT

emp.ename,

emp.salary,

t2.*

FROM

emp,

salarygrade t2

WHERE

emp.salary >= t2.losalary

AND emp.salary <= t2.hisalary

查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级


/*

分析:

 1. 员工编号,员工姓名,工资 信息在emp 员工表中

 2. 职务名称,职务描述 信息在 job 职务表中

 3. job 职务表 和 emp 员工表 是 一对多的关系 emp.job_id = job.id

 4. 部门名称,部门位置 来自于 部门表 dept

 5. dept 和 emp 一对多关系 dept.id = emp.dept_id

 6. 工资等级 信息在 salarygrade 工资等级表中

 7. emp.salary >= salarygrade.losalary  and emp.salary <= salarygrade.hisalary

*/

SELECT

emp.id,

emp.ename,

emp.salary,

job.jname,

job.description,

dept.dname,

dept.loc,

t2.grade

FROM

emp

INNER JOIN job ON emp.job_id = job.id

INNER JOIN dept ON dept.id = emp.dept_id

INNER JOIN salarygrade t2 ON emp.salary BETWEEN t2.losalary and t2.hisalary;


查询出部门编号、部门名称、部门位置、部门人数


/*

分析:

 1. 部门编号、部门名称、部门位置 来自于部门 dept 表

 2. 部门人数: 在emp表中 按照dept_id 进行分组,然后count(*)统计数量

 3. 使用子查询,让部门表和分组后的表进行内连接

*/

-- 根据部门id分组查询每一个部门id和员工数

select dept_id, count(*) from emp group by dept_id;

SELECT

dept.id,

dept.dname,

dept.loc,

t1.count

FROM

dept,

(

 SELECT

  dept_id,

  count(*) count

 FROM

  emp

 GROUP BY

  dept_id

) t1

WHERE

dept.id = t1.dept_id

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
关系型数据库 MySQL 调度
MySQL高级功能与优化策略深度探索
MySQL高级功能与优化策略深度探索
|
5月前
|
关系型数据库 MySQL 数据库
关系型数据库MySQL开发要点之多表查询2024详解
关系型数据库MySQL开发要点之多表查询2024详解
34 2
|
5月前
|
关系型数据库 MySQL 数据库
MySQL数据库开发之多表查询数据准备及案例实操
MySQL数据库开发之多表查询数据准备及案例实操
47 1
|
5月前
|
关系型数据库 MySQL 数据库
MySQL数据库基础第四篇(多表查询与事务)
MySQL数据库基础第四篇(多表查询与事务)
|
5月前
|
SQL 存储 关系型数据库
精通MySQL:从基础到高级应用与最佳实践
第一章:MySQL基础入门 1.1 MySQL概述 介绍MySQL的历史、发展、优势以及应用领域
|
5月前
|
SQL 关系型数据库 MySQL
MySQL数据库——基础篇总结(概述、SQL、函数、约束、多表查询、事务)一
MySQL数据库——基础篇总结(概述、SQL、函数、约束、多表查询、事务)一
47 5
|
5月前
|
关系型数据库 MySQL 数据库
MySQL数据库——多表查询(4)-实例练习、多表查询总结
MySQL数据库——多表查询(4)-实例练习、多表查询总结
146 1
|
5月前
|
SQL 关系型数据库 MySQL
深入探索MySQL SELECT查询:从基础到高级,解锁数据宝藏的密钥
深入探索MySQL SELECT查询:从基础到高级,解锁数据宝藏的密钥
|
5月前
|
SQL 安全 关系型数据库
深入理解MySQL:从基础到高级应用及安全管理
第一章:MySQL基础入门 1.1 MySQL简介 简要介绍MySQL的历史、发展以及它在当前数据库领域的应用
|
5月前
|
SQL 存储 关系型数据库
精通MySQL:从基础到高级应用
第一章:MySQL入门 1.1 MySQL简介 介绍MySQL的历史、特点以及它作为关系型数据库管理系统(RDBMS)的优势
下一篇
无影云桌面