EmmmuaCode EmmmuaCode
首页​
导航🚀​
  • 数据结构
  • 计算机网络
  • Java基础

    • JavaSE
    • JVM虚拟机
    • JUC并发编程
  • JavaWeb

    • Servlet
    • MVC
    • filter|listener
  • HTML
  • CSS
  • JavaScript
  • Vue
  • uni-app
  • Spring5
  • SpringMVC
  • SpringBoot2
  • SpringCloud
  • SpringSecurity
  • 搜索引擎

    • ElasticSearch
  • 消息队列

    • RabbitMQ
  • 服务器

    • Nginx🌐
  • 服务框架

    • Dubbo
  • Python基础
  • 数据分析
  • Hadoop
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • NoSQL数据库概论
    • Redis
    • MongoDB
    • HBase
  • 框架

    • MyBatis
    • MyBatis-Plus
    • ShardingSphere
  • 部署

    • Linux
    • Docker
  • 管理

    • Maven
    • Git
  • 友情链接
  • 优秀博客文章
  • 索引

    • 分类
    • 标签
    • 归档
  • 其他

    • 关于
Github (opens new window)

wufan

海内存知己,天涯若比邻。
首页​
导航🚀​
  • 数据结构
  • 计算机网络
  • Java基础

    • JavaSE
    • JVM虚拟机
    • JUC并发编程
  • JavaWeb

    • Servlet
    • MVC
    • filter|listener
  • HTML
  • CSS
  • JavaScript
  • Vue
  • uni-app
  • Spring5
  • SpringMVC
  • SpringBoot2
  • SpringCloud
  • SpringSecurity
  • 搜索引擎

    • ElasticSearch
  • 消息队列

    • RabbitMQ
  • 服务器

    • Nginx🌐
  • 服务框架

    • Dubbo
  • Python基础
  • 数据分析
  • Hadoop
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • NoSQL数据库概论
    • Redis
    • MongoDB
    • HBase
  • 框架

    • MyBatis
    • MyBatis-Plus
    • ShardingSphere
  • 部署

    • Linux
    • Docker
  • 管理

    • Maven
    • Git
  • 友情链接
  • 优秀博客文章
  • 索引

    • 分类
    • 标签
    • 归档
  • 其他

    • 关于
Github (opens new window)
  • MySQL-基础

    • MySQL-简介
    • MySQL-CRUD
    • MySQL-函数
    • MySQL 多表查询
      • mysql多表查询
        • 问题的引出(重点,难点)
        • 说明
        • 多表查询练习
        • 自连接
      • mysql表子查询
        • 什么是子查询
        • 单行子查询
        • 多行子查询
        • 在多行子查询中使用 all 操作符
        • 在多行子查询中使用 any 操作符
        • 多列子查询
        • 在 from 子句中使用子查询
      • 表复制
        • 自我复制数据(蠕虫复制)
      • 合并查询
        • 介绍
        • 外连接
        • 课堂练习
    • MySQL 约束与自增长
    • MySQL 索引与事务
    • MySQL 表类型和存储引擎
    • MySQL 视图与管理
  • MySQL-进阶

    • MySQL 存储引擎
    • MySQL 索引
    • MySQL SQL优化
    • MySQL 视图/存储过程/触发器
    • MySQL 锁
    • MySQL InnoDB引擎
    • MySQL 管理
  • MySQL-运维

    • MySQL 日志
    • MySQL 主从复制
    • MySQL 分库分表
    • MySQL 读写分离
  • NoSQL 数据库概论

    • 非关系型数据库
    • NoSQL数据库理论基础
    • NoSQL数据库分类
  • Redis

    • Redis 数据库简介
    • Redis 概述安装
    • 常用五大数据类型
    • Redis 配置文件
    • Redis 发布和订阅
    • Redis 新数据类型
    • Redis Java整合
    • Redis 事务与锁
    • Redis 持久化操作
    • Redis 主从复制
    • Redis 集群搭建
    • Redis 缓存问题
    • Redis 分布式锁
    • Redisson 的应用
    • Redis 6.0新功能
  • MongoDB

    • MongoDB 相关概念
    • MongoDB 安装
    • MongoDB 常用命令
    • MongoDB 索引-Index
    • MongoDB 整合Java案例
    • MongoDB 集群和安全
  • HBase

    • HBase简介
    • HBase系统架构
    • HBase数据定义
    • HBase数据操作
    • HBase基本原理
  • MyBatis

    • MyBatis 入门案例
    • XML 配置
    • XML 映射文件
    • 动态SQL
    • 缓存
    • MyBatis的逆向工程
    • 分页插件
  • MyBatis-Plus

    • MyBatis-Plus 简介
    • MyBatis-Plus 入门案例
    • MyBatis-Plus 基本CRUD
    • MyBatis-Plus 常用注解
    • 条件构造器和常用接口
    • MyBatis-Plus 插件
    • MyBatis-Plus 通用枚举
    • MyBatis-Plus 代码生成器
    • MyBatis-Plus 多数据源
    • MyBatisX插件
  • ShardingSphere

    • ShardingSphere_高性能架构模式
    • ShardingSphere 简介
    • ShardingSphere 主从同步
    • ShardingSphere_JDBC 读写分离
    • ShardingSphere-JDBC垂直分片
    • ShardingSphere-JDBC水平分片
    • 启动ShardingSphere-Proxy
    • ShardingSphere-Proxy读写分离
    • ShardingSphere-Proxy垂直分片
  • studynotes
  • database
  • MySQL
wufan
2022-09-13
目录

MySQL 多表查询

# MySQL 多表查询

# mysql多表查询

# 问题的引出(重点,难点)

04

# 说明

多表查询是指基于两个和两个以上的表查询.在实际应用中,查询单个表可能不能满足你的需求.

# 多表查询练习

04

-- 多表查询
-- 显示雇员名,雇员工资及所在部门的名字【笛卡尔积】
SELECT * FROM salgrade
SELECT * FROM emp
SELECT * FROM dept
/*
   分析
   1.雇员名,雇员工资 来自 emp表
   2.部门的名字,来自dept表
   (1)从第一张表中,取出一行和第二张表的每一行进行组合,返回结果[含有两张表的所有列]
   (2)一共返回的记录数第一张表行数*第二张表的行数
   (3)这样多表查询默认处理返回的结果,称为【笛卡尔积】
   (4)解决这个多表的关键就是要写出正确的过滤条件 where
   3.当我们需要指定显示某个表的列时,需要 表.列名
   
   
*/
SELECT  ename,sal,dname,emp.deptno 
	FROM emp,dept
	WHERE emp.deptno=dept.deptno
-- 小技巧:多表查询的条件下不能少于 表的个数-1,否则会出现笛卡尔积

-- 如何显示部门号为10的部门名、员工名和工资
SELECT  ename,sal,dname,emp.deptno 
	FROM emp,dept
	WHERE emp.deptno=dept.deptno AND emp.deptno=10
	
-- 显示各个员工的姓名,工资,及其工资的级别
SELECT ename,sal,grade
	FROM emp,salgrade
	WHERE sal >= losal AND sal<=hisal;
	
-- 显示雇员名,雇员工资及所在部门的名字,并按部门排序
  SELECT ename,sal,dname,emp.deptno
		FROM emp,dept
		WHERE emp.deptno=dept.deptno
		ORDER BY emp.deptno DESC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 自连接

自连接是指在同一张表的连接查询[将同一张表看做两张表].

-- 多表查询的 自连接

-- 思考题:显示公司员工名字和他的上级名字
SELECT *FROM emp
-- 分析:员工名字 在emp,上级的名字 emp
-- 员工和上级是通过 emp表的 mgr 列并联
-- 小结:1.把同一张表当做两张表来使用
--       2.需要给表取别名[表别名]
--       3.列名不明确,可以指定列的别名,列名 AS 列的别名
SELECT worker.ename AS '职员名',boss.ename AS '上级名'
	FROM emp worker,emp boss
	WHERE worker.mgr=boss.empno;
1
2
3
4
5
6
7
8
9
10
11
12

# mysql表子查询

# 什么是子查询

子查询是指嵌入在其它 sql 语句中的 select 语句,也叫嵌套查询

# 单行子查询

单行子查询是指只返回一行数据的子查询语句

请思考:如何显示与 SMITH 同一部门的所有员工?

# 多行子查询

多行子查询指返回多行数据的子查询 ,使用关键字 in

如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号、但是不含10自己的。

-- 子查询的演示
-- 请思考:如何显示与SMITH 同一部门的所有员工

/*
  1.先查询到SMITH的部门号得到
  2.把上面的select语句当做一个子查询来使用
*/
SELECT deptno
	FROM emp
	WHERE ename='SMITH'
	
SELECT *
	FROM emp
	WHERE deptno =(
		SELECT deptno
		FROM emp
		WHERE ename='SMITH'
	)
-- 课堂练习:如何查询和部门10的工作相同的雇员的
--   名字、岗位、工资、部门号、但是不含10部门自己的

/*
   1.查询到10号部门有哪些工作
   2.把上面查询的结果当做子查询
*/
SELECT DISTINCT job 
	FROM emp
	WHERE deptno=10;
	
-- 下面语句完整
SELECT ename,job,sal,deptno
	FROM emp
	WHERE job IN (
		SELECT DISTINCT job 
		FROM emp
		WHERE deptno=10
	)AND deptno !=10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 在多行子查询中使用 all 操作符

-- all 和 any 的使用

-- 请思考:显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

SELECT ename,sal,deptno
	FROM emp
	WHERE sal> ALL(
		SELECT sal
		FROM emp
		WHERE deptno =30)
		
-- 可以这样写
SELECT ename,sal,deptno
	FROM emp
	WHERE sal> (
		SELECT MAX(sal)
		FROM emp
		WHERE deptno =30)
		

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 在多行子查询中使用 any 操作符

-- 请思考:如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号

SELECT ename,sal,deptno
	FROM emp
	WHERE sal> ANY(
		SELECT sal
		FROM emp
		WHERE deptno =30)
-- 可以这样写
SELECT ename,sal,deptno
	FROM emp
	WHERE sal> (
		SELECT MIN(sal)
		FROM emp
		WHERE deptno =30)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 多列子查询

多列子查询是指查询返回多个列数据的子查询语句。

-- 多列子查询
-- 请思考如何查询与allen的部门和岗位完全相同的所有雇员(并且不含smith本人)
-- (字段1,字段2...)=(select 字段1 ,字段2 from...)

-- 分析:1.得到allen的部门和岗位

SELECT deptno,job
	FROM emp
	WHERE ename='ALLEN'
	
-- 分析:2.把上面的查询当做子查询来使用,并且使用多列子查询的语法进行匹配
SELECT * 	
	FROM emp
	WHERE (deptno,job)=(
		SELECT deptno,job
		FROM emp
		WHERE ename='ALLEN'
		)AND ename != 'ALLEN'
		
-- 请查询和宋江同学数学,英语,语文
-- 成绩完全相同的同学		
SELECT *
	FROM student
	WHERE (chinese,english,math)=(	
		SELECT chinese,english,math 
		FROM student
		WHERE `name`='宋江');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 在 from 子句中使用子查询

请思考:查找每个部门工资高于本部门平均工资的人的资料

这里要用到数据查询的小技巧,把一个子查询当作一个临时表使用 请思考:查找每个部门工资最高的人的详细资料

-- 子查询 练习

-- 请思考:查找每个部门工资高于本部门平均工资的人的资料
-- 这里要用到数据查询的小技巧,把一个子查询当做一个临时表使用

-- 1.先得到每个部门的 部门号和对应的平均工资
SELECT deptno,AVG(sal)
	FROM emp
	GROUP BY deptno
	
	
-- 2.把上面的结果当做子查询,和emp进行多表查询
SELECT  ename,sal,temp.avg_sal,emp.deptno
	FROM emp,(
		SELECT deptno,AVG(sal) AS avg_sal
		FROM emp
		GROUP BY deptno
		)temp
		WHERE emp.deptno=temp.deptno AND emp.sal>temp.avg_sal
		
-- 查找每个部门工资最高的人详细资料
SELECT  ename,sal,temp.max_sal,emp.deptno
	FROM emp,(
		SELECT deptno,MAX(sal) AS max_sal
		FROM emp
		GROUP BY deptno
		)temp
		WHERE emp.deptno=temp.deptno AND emp.sal=temp.max_sal
		
-- 查询每个部门的信息(包括:部门名,编号,地址)和人员数量
-- 1.部门名,编号,地址
-- 2.各个部门的数量
SELECT COUNT(*),deptno 
	FROM emp
	GROUP BY deptno
	
	
	
SELECT dname,dept.deptno ,loc,tmp.per_num AS '人数'
	FROM dept,(
		SELECT COUNT(*) AS per_num,deptno 
		FROM emp
		GROUP BY deptno
		) tmp
		WHERE tmp.deptno=dept.deptno
		
-- 还有一种写法 表.* 表示将该所有列都显示出来
-- 在多表查询中,当多个表的列不重复时,才可以直接写列名

SELECT tmp.* ,dname,loc
	FROM dept,(
		SELECT COUNT(*) AS per_num,deptno
		FROM emp
		GROUP BY deptno
		) tmp
		WHERE tmp.deptno=dept.deptno	

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# 表复制

# 自我复制数据(蠕虫复制)

有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据。

思考题:如何删除掉一张表重复记录

-- 表的复制
-- 为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据

CREATE TABLE my_tab01(
	id INT,
	`name` VARCHAR(32),
	sal DOUBLE,
	job VARCHAR(32),
	deptno INT);
DESC my_tab01
SELECT * FROM my_tab01

-- 演示如何自我复制
-- 1.先把emp表的记录复制到my_tab01
INSERT INTO my_tab01
	(id,`name`,sal,job,deptno)
	SELECT empno,ename,sal,job,deptno FROM emp;
	
-- 2.自我复制
INSERT INTO my_tab01
	SELECT * FROM my_tab01;
	
-- 如何删除一张表重复记录
-- 1.先创建一张表 my_tab02,
-- 2.让 my_tab02 有重复的记录

CREATE TABLE my_tab02 LIKE emp;-- 这个语句把emp表的结构(列),复制到my_tab02

DESC my_tab02; 

INSERT INTO my_tab02
	SELECT * FROM emp;
	
SELECT * FROM my_tab02;
-- 3.考虑去重
/*
	(1)先创建一张临时表,my_tmp,该表的结构和 my_tab02一样
	(2)把my_tmp的记录通过 distinct关键字 处理后,把记录复制到my_tmp
	(3)清除掉my_tab02 记录
	(4)把 my_tmp 表的记录复制到my_tab02
	(5)drop 掉 临时表my_tmp
*/
DROP TABLE my_tmp
-- (1)先创建一张临时表,my_tmp,该表的结构和 my_tab02一样
CREATE TABLE my_tmp LIKE my_tab02
-- (2)把my_tmp的记录通过 distinct关键字 处理后,把记录复制到my_tmp
INSERT INTO my_tmp
	SELECT DISTINCT * FROM my_tab02
-- (3)清除掉my_tab02 记录
DELETE FROM my_tab02
-- (4)把 my_tmp 表的记录复制到my_tab02
INSERT INTO my_tab02
	SELECT * FROM my_tmp
-- (5)drop 掉 临时表my_tmp
DROP TABLE my_tmp

SELECT * FROM my_tab02


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 合并查询

# 介绍

有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号union , union all

  1. nuion all
    • 该操作符用于取得两个结果集的并集。当使用该操作符时,不会取消重复行。
  2. union
    • 该操作赋与union all相似,但是会自动去掉结果集中重复行。.
-- 合并查询

SELECT ename,sal,job FROM emp WHERE sal>2500 -- 5

SELECT ename,sal,job FROM emp WHERE job='MANAGER' -- 3

-- union all 就是将两个查询结果合并,不会去重
SELECT ename,sal,job FROM emp WHERE sal>2500
UNION ALL
SELECT ename,sal,job FROM emp WHERE job='MANAGER'-- 8

-- union  就是两个查询结果合并,会去重,不会出现同步记录
SELECT ename,sal,job FROM emp WHERE sal>2500
UNION 
SELECT ename,sal,job FROM emp WHERE job='MANAGER'-- 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 外连接

  1. 左外连接(如果左侧的表完全显示我们就说是左外连接) select...from 表1 left join 表2 on条件 [表1:左表 表2:右表]
  2. 右外连接(如果右侧的表完全显示我们就说是右外连接) select...from 表1 rigth join 表2 on条件 [表1:左表 表2:右表]

-- 表stu --表exam

id name id grade

1 Jack 1 56

2 Tom 2 76

3 Kity 11 8

4 nono

  1. 使用左连接(显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)
-- 外连接
-- 比如:列出部门名称和这些部门的员工名称和工作,同时要求 显示出那些没有员工的部门

-- 使用我们学习过的多表查询的sql,看看效果

SELECT dname,ename,job 
	FROM emp,dept
	WHERE emp.deptno=dept.deptno
	ORDER BY dname
	
-- 先创建 stu
CREATE TABLE stu(
	id INT,
	`name` VARCHAR(32));
INSERT INTO stu VALUES(1,'Jack'),(2,'tom'),(3,'kity'),(4,'nono');
SELECT * FROM stu;

-- 创建exam
CREATE TABLE exam(
	id INT,
	grade INT);
INSERT INTO exam VALUES(1,56),(2,76),(11,8);
SELECT * FROM exam;


-- 使用左连接
-- (显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)
SELECT `name`,stu.id,grade
	FROM stu,exam
	WHERE stu.id=exam.id;
	
-- 改成左外连接
SELECT `name`,stu.id,grade
	FROM stu LEFT JOIN exam
	ON stu.id=exam.id;
	
-- 使用右外连接(显示所有人的成绩,如果没有名字匹配,显示为空)
-- 即:右边的表(exam)和左表没有匹配的记录,也会把右表的记录显示出来
SELECT `name`,stu.id,grade
	FROM stu RIGHT JOIN exam
	ON stu.id=exam.id;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 课堂练习

列出部门名称和这些部门的员工信息(名字和工作),同时列出那些没有员工的部门名。5min 1.使用左外连接实现

2.使用右外连接实现

-- 列出部门名称和这些部门的员工信息(名字和工作),
-- 同时列出那些没有员工的部门名。5min
-- 1使用左外连接实现
SELECT dname,ename,job
	FROM dept LEFT JOIN emp
	ON emp.deptno=dept.deptno

-- 2.使用右外连接实现	
SELECT dname,ename,job
	FROM emp RIGHT JOIN dept
	ON emp.deptno=dept.deptno
1
2
3
4
5
6
7
8
9
10
11
#MySQL
上次更新: 2024/04/21, 09:42:22
MySQL-函数
MySQL 约束与自增长

← MySQL-函数 MySQL 约束与自增长→

最近更新
01
微信支付功能的实现与流程
11-21
02
购物车与结算区域的深入优化与功能完善
11-21
03
购物车与结算区域的功能实现与优化
11-21
更多文章>
Theme by Vdoing | Copyright © 2023-2024 EmmmuaCode | 黔ICP备2022009864号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式