【JavaWeb后端学习笔记】MySQL多表查询(内连接、外连接、子查询)
MySQL 多表查询
- 1、连接查询
- 1.1 内连接
- 1.2 外连接
- 2、子查询
- 2.1 标量子查询
- 2.2 列子查询
- 2.3 行子查询
- 2.4 表子查询
- 3、多表查询案例
多表查询有两大类:连接查询和子查询。
连接查询又分为隐式/显式内连接和左/右外连接。
子查询又分为标量子查询、列子查询、行子查询和表子查询。
多表查询是建立在单表查询的基础之上的,因此需要熟练单表查询。可以参考:【JavaWeb后端学习笔记】MySQL的数据查询语言(Data Query Language,DQL)
本文案例所需资料来自黑马程序员:多表查询
开始前需要运行01.数据准备.sql脚本中的代码,准备表和数据。
1、连接查询
1.1 内连接
内连接相当于查询A、B两个表交集部分数据。
内连接有两种:隐式内连接、显示内连接。他们的语法如下:
-- 隐式内连接语法
select 字段列表 from 表1,表2 where 连接条件...;-- 显示内连接语法
select 字段列表 from 表1 [inner] join 表2 on 连接条件...;
由于现在是多表查询的情况,因此在返回字段列表中,需要使用表名.字段名的格式。
连接条件是用来消除多余的笛卡尔积。一般会使用逻辑外键消除笛卡尔积。
下面分别使用隐式内连接和现实内连接的方式查询员工的姓名以及所属部门名称。
-- A. 查询员工的姓名 , 及所属的部门名称 (隐式内连接实现)
-- tb_emp表中的dept_id字段是关联到tb_dept表的逻辑外键,可以通过逻辑外键消除多余的笛卡尔积。
select tb_emp.name as name, tb_dept.name as department from tb_emp, tb_dept where tb_emp.dept_id = tb_dept.id;-- B. 查询员工的姓名 , 及所属的部门名称 (显式内连接实现)
-- 显式内连接只是在代码编写上将内连接展现出来,效果与隐式内连接相同
-- 显示内连接的连接条件写在 on 后面。
select tb_emp.name as name, tb_dept.name as department from tb_emp inner join tb_dept on tb_emp.dept_id = tb_dept.id;
这里可以注意一点,员工表中有17条数据,但是查出来的结果只有16条,缺少了员工姓名为“陈友谅”的数据,这是因为“陈友谅”的dept_id为null,他没有对应的部门,在部门表中没有id为null的数据,因此在内连接查询中,连接条件是不成立的,所以查询不到“陈友谅”的数据。但是为了保证员工数据的完整性,虽然“陈友谅”没有工作,也任然需要把他查询出来,这个时候就需要使用外连接查询。
1.2 外连接
外连接分为:左外连接和右外连接。
左外连接:查询左表所有数据(包括两张表的交集);
右外连接:查询右表所有数据(包括两张表的交集);
外连接语法如下:
-- 左外连接语法
select 字段列表 from 表1 left [outer] join 表2 on 连接条件...;-- 右外连接语法
select 字段列表 from 表1 right [outer] join 表2 on 连接条件...;
外连接的连接条件也是写在 “on” 后面。
下面分别使用左外连接和右外连接查询员工表所有员工的姓名, 和对应的部门名称:
-- A. 查询员工表 所有 员工的姓名, 和对应的部门名称 (左外连接)
-- 使用左外连接,为了查询出所有员工数据,将员工表tb_emp放在左边
select tb_emp.name as 员工姓名, tb_dept.name as 部门名称 from tb_emp left join tb_dept on tb_emp.dept_id = tb_dept.id;-- B. 查询部门表 所有 部门的名称, 和对应的员工名称 (右外连接)
-- 使用右外连接,为了查询出所有员工数据,将员工表tb_emp放在右边
select tb_emp.name as 员工姓名, tb_dept.name as 部门名称 from tb_dept right join tb_emp on tb_emp.dept_id = tb_dept.id;
从查询结果可以发现,虽然“陈友谅”的dept_id为null,但是该员工任然查询出来了。这是因为外连接保证了查询出某一边表格的所有数据。
2、子查询
SQL语句中嵌套select语句,称为嵌套查询,又称子查询。
子查询语法:
-- 子查询语法(形式不固定)
select * from t1 where column1 = (select column2 from t2 ...);select * from (select * from t1 where 条件查询条件) t left join t2 on 连接条件;......
子查询外部的语句可以是insert/update/delete/select的任何一个,最常见的是select
子查询 | 返回结果及常用操作符 |
---|---|
标量子查询 | 返回的结果为单个值;常用操作符:= 、<>、>、>=、<、<= |
列子查询 | 返回的结果为一列;常用操作符:in、not in等 |
行子查询 | 返回的结果为一行;常用操作符:=、<>、in、not in |
表子查询 | 返回的结果为多行多列;常用操作符:in |
2.1 标量子查询
标量子查询返回的结果为单个值。
可以与返回结果比较大小,因此常用操作符有:= 、<>、>、>=、<、<=。
案例1:查询 “教研部” 的所有员工信息。
分析:首先需要查询出教研部的id,然后使用员工表中的dept_id与教研部id判断是否相等。
-- 查询 "教研部" 的所有员工信息
-- (select id from tb_dept where name = '教研部') 标量子查询查询出教研部id
select * from tb_emp where dept_id = (select id from tb_dept where name = '教研部');
案例2:查询在 “方东白” 入职之后的员工信息。
分析:首先查询出姓名为 "方东白"的员工的入职时间,然后与该入职时间比较。
-- 查询在 "方东白" 入职之后的员工信息
-- (select entrydate from tb_emp where name = '方东白') 标量子查询查询出"方东白" 入职时间
select * from tb_emp where entrydate > (select entrydate from tb_emp where name = '方东白');
2.2 列子查询
列子查询返回的结果为一列。
列子查询返回结果相当于一个列表或者集合,可以判断某个字段值是否在这个列表之中,因此常用操作符有:in、not in等。
案例:查询 “教研部” 和 “咨询部” 的所有员工信息。
分析:需要查询出"教研部" 和 "咨询部"的id,组成一个集合。通过判断员工所属的dept_id是否在这个集合内来查询结果。
-- 查询 "教研部" 和 "咨询部" 的所有员工信息。
-- (select id from tb_dept where tb_dept.name in ('教研部', '咨询部') 列子查询返回'教研部' 和 '咨询部'的id集合
select * from tb_emp where dept_id in (select id from tb_dept where tb_dept.name in ('教研部', '咨询部'));
2.3 行子查询
行子查询返回的结果为一行。
行子查询返回结果为表中一行完整数据或部分数据,可以与这一行数据的任意字段进行比较,常用操作符有:=、<>、in、not in。
案例:查询与 “韦一笑” 的入职日期 及 职位都相同的员工信息 。
分析:首先需要查询出 “韦一笑” 的入职日期 及 职位。然后根据这些信息进行判断。由于要对两个字段同时进行判断,因此可以用 ( ) 将这两个字段括起来同时判断。
-- 查询与 "韦一笑" 的入职日期 及 职位都相同的员工信息 ;-- 首先尝试采用标量子查询,分别查询出"韦一笑"的入职日期 及 职位,但是这样就需要两次子查询,性能较低。
select * from tb_emp where entrydate = (select entrydate from tb_emp where name = '韦一笑') and job = (select job from tb_emp where name = '韦一笑') and name != '韦一笑';-- 采用行子查询,查询出的结果为一行,可以将需要比较的字段用 ( ) 括起来进行比较
select * from tb_emp where (entrydate, job) = (select entrydate, job from tb_emp where name = '韦一笑') and name != '韦一笑';
2.4 表子查询
表子查询返回的结果为多行多列。
常用操作符为:in。
案例:查询入职日期是 “2006-01-01” 之后的员工信息 , 及其部门名称
分析:有两种思路。第一种,先建立员工表与部门表的外连接,通过逻辑外键消除多余的笛卡尔积,然后判断入职时间。第二种,先通过select返回入职时间在 “2006-01-01” 之后的员工子表,然后建立外连接,通过逻辑外键消除多余的笛卡尔积。推荐使用外连接,保证员工信息完整。
--查询入职日期是 "2006-01-01" 之后的员工信息 , 及其部门名称-- 先建立外连接,后判断入职时间
select tb_emp.*, tb_dept.name as 部门名称 from tb_emp left join tb_dept on tb_emp.dept_id = tb_dept.id where tb_emp.entrydate > '2006-01-01';-- 表子查询。先查询出入职时间在 "2006-01-01" 之后员工信息子表,然后建立外连接。
select e.*, d.name 部门名称 from (select * from tb_emp where entrydate > '2006-01-01') e left join tb_dept d on e.dept_id = d.id;
3、多表查询案例
准备数据:执行01.多表查询数据准备.sql脚本。
从案例-多表查询.vsdx中可以看到四张表的详细信息。
-- 1. 查询价格低于 10元 的菜品的名称 、价格 及其 菜品的分类名称 .
-- 子查询
select d.name 名称, d.price 价格, c.name 分类
from (select * from dish where price < 10) d left join category c on d.category_id = c.id;
-- 内连接
select d.name 菜品名称, d.price 价格, c.name 菜品分类
from dish d, category c
where d.category_id = c.id and d.price < 10;-- 2. 查询所有价格在 10元(含)到50元(含)之间 且 状态为'起售'的菜品名称、价格 及其 菜品的分类名称 (即使菜品没有分类 , 也需要将菜品查询出来).
-- 子查询
select d.name 名称, d.price 价格, c.name 分类
from (select * from dish where price between 10 and 50 and status = 1) d left join category c on d.category_id = c.id;
-- 左外连接
select d.name 菜品名称, d.price 价格, c.name 菜品分类
from dish d left join category c on d.category_id = c.id
where d.price between 10 and 50 and d.status = 1;-- 3. 查询每个分类下最贵的菜品, 展示出分类的名称、最贵的菜品的价格 .
select c.name 分类名称, max(d.price) 最大价格
from dish d, category c
where d.category_id = c.id
group by c.name;-- 4. 查询各个分类下 状态为 '起售' , 并且 该分类下菜品总数量大于等于3 的 分类名称 .
select c.name 分类名称
from dish d, category c
where d.category_id = c.id and d.status = 1
group by c.name
having count(*) >= 3;-- 5. 查询出 "商务套餐A" 中包含了哪些菜品 (展示出套餐名称、价格, 包含的菜品名称、价格、份数).
select s.name 套餐名称,s.price 套餐价格,d.name 菜品名称,d.price 菜品价格,sd.copies 菜品份数
from dish d,setmeal_dish sd,setmeal s
where d.id = sd.dish_idand sd.setmeal_id = s.idand s.name = '商务套餐A';-- 6. 查询出低于菜品平均价格的菜品信息 (展示出菜品名称、菜品价格).
select name, price
from dish
where price < (select avg(price) from dish);
相关文章:
【JavaWeb后端学习笔记】MySQL多表查询(内连接、外连接、子查询)
MySQL 多表查询 1、连接查询1.1 内连接1.2 外连接 2、子查询2.1 标量子查询2.2 列子查询2.3 行子查询2.4 表子查询 3、多表查询案例 多表查询有两大类:连接查询和子查询。 连接查询又分为隐式/显式内连接和左/右外连接。 子查询又分为标量子查询、列子查询、行子查询…...

RocketMQ 过滤消息 基于tag过滤和SQL过滤
RocketMQ 过滤消息分为两种,一种tag过滤,另外一种是复杂的sql过滤。 tag过滤 首先创建producer然后启动,在这里创建了字符串的数组tags。字符串数组里面放置了多个字符串,然后去发送15条消息。 15条消息随着i的增长,…...

element-ui 基本样式的一些更改【持续更新】
1、 去除el-tabs的底部灰色横线 ::v-deep .el-tabs__nav-wrap::after {height: 0px;}2、el-table设置表头颜色 <el-table:data"tableData":header-cell-style"{background:#F7F8FA,color:#4E5869}"><el-table-columnlabel"序号"type&qu…...
element-ui radio和checkbox禁用时不置灰还是原来不禁用时的样式
把要紧用的内容加上一个class"notEdit-page" z注意要在style里面写不能加上scoped /*//checkBox自定义禁用样式*//*//checkBox自定义禁用样式*/ .notEdit-page.el-checkbox__input.is-disabled.is-checked.el-checkbox__inner::after {border-color: #fff; } .notEdi…...
第一部分:基础知识 6. 函数 --[MySQL轻松入门教程]
MySQL 提供了丰富的内置函数,涵盖了字符串处理、数值计算、日期时间操作、聚合分析以及控制流等多个方面。这些函数可以帮助用户更高效地进行数据查询和处理。 1.字符串函数 MySQL 提供了丰富的字符串函数来帮助用户处理和操作字符串数据。下面是一些常用的 MySQL…...
【蓝桥杯每日一题】扫雷
扫雷 知识点 2024-12-3 蓝桥杯每日一题 扫雷 dfs (bfs也是可行的) 题目大意 在一个二维平面上放置这N个炸雷,每个炸雷的信息有$(x_i,y_i,r_i) $,前两个是坐标信息,第三个是爆炸半径。然后会输入M个排雷火箭࿰…...

【算法】棋盘覆盖问题源代码及精简版
目录 一、题目 二、样例 三、示例代码 四、精简代码 五、总结 对于棋盘覆盖问题的解答和优化。 一、题目 输入格式: 第一行,一个整数n(棋盘n*n,n确保是2的幂次,n<64) 第二行,两个整数…...
Django的介绍
Django是一个高级的Python Web框架,它鼓励快速开发和干净、实用的设计。Django遵循MVC设计模式,即模型(Model)、视图(View)和控制器(Controller),并提供了一个即时可用的…...

【Spring工具插件】lombok使用和EditStarter插件
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 引入 一:lombok介绍 1:引入依赖 2:使用 3:原理 4&…...

掌控时间,成就更好的自己
在个人成长的道路上,时间管理是至关重要的一环。有效的时间管理能够让我们更加高效地完成任务,实现自己的目标,不断提升自我。 时间对每个人都是公平的,一天只有 24 小时。然而,为什么有些人能够在有限的时间里做出卓…...
Ruby On Rails 笔记2——表的基本知识
Active Record Basics — Ruby on Rails Guides Active Record Migrations — Ruby on Rails Guides 原文链接自取 1.Active Record是什么? Active Record是MVC模式中M的一部分,是负责展示数据和业务逻辑的一层,可以帮助你创建和使用Ruby…...

【AI系统】EfficientNet 系列
EfficientNet 系列 本文主要介绍 EffiicientNet 系列,在之前的文章中,一般都是单独增加图像分辨率或增加网络深度或单独增加网络的宽度,来提高网络的准确率。而在 EfficientNet 系列论文中,会介绍使用网络搜索技术(NAS)去同时探索…...
【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的!现在用Python写代码的人还多吗?
【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的!现在用Python写代码的人还多吗? 【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的&a…...
蓝桥杯分治
P1226 【模板】快速幂 题目描述 给你三个整数 𝑎,𝑏,𝑝a,b,p,求 𝑎𝑏 mod 𝑝abmodp。 输入格式 输入只有一行三个整数,分别代表 𝑎,𝑏,𝑝a,b,p。…...

YOLOv8实战无人机视角目标检测
本文采用YOLOv8作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv8以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对无人机目标数据集进行训练和优化,该数据集包含丰富的无人机目标图像…...
三、【docker】docker和docker-compose的常用命令
文章目录 一、docker常用命令1、镜像管理2、容器管理3、容器监控和调试4、网络管理5、数据卷管理6、系统维护7、实用组合命令8、常用技巧二、docker-compose常用命令1、基本命令2、构建相关3、运行维护4、常用组合命令5、实用参数 一、docker常用命令 1、镜像管理 # 查看本地…...

Qt 2D绘图之五:图形视图框架的结构、坐标系统和框架间的事件处理与传播
参考文章链接: Qt 2D绘图之五:图形视图框架的结构和坐标系统 Qt 2D绘图之六:图形视图框架的事件处理与传播 图形视图框架的结构 在前面讲的基本绘图中,我们可以自己绘制各种图形,并且控制它们。但是,如果需要同时绘制很多个相同或不同的图形,并且要控制它们的移动、…...

基于SpringBoot+Vue的美妆购物网站
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...

MySQL之创建和管理表
目录 1. MySQL中的数据类型编辑编辑 2. 创建和管理数据库 方式1:创建数据库 方式2:创建数据库并指定字符集 方式3:判断数据库是否已经存在,不存在则创建数据库( 推荐 ) 总结 2.2 使用数据库 查看当…...

肌肉骨骼肿瘤治疗市场:潜力无限,未来可期
肌肉骨骼肿瘤治疗作为现代医学的重要分支,专注于应对骨骼和肌肉系统中的良性和恶性肿瘤。随着全球人口老龄化和生活方式的改变,肌肉骨骼疾病日益成为公共卫生的重要问题。与此同时,医疗技术的进步和患者对高质量医疗服务的需求不断推动该市场…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...

[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...