当前位置: 首页 > news >正文

【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 字段列表 from1,2 where 连接条件...;-- 显示内连接语法
select 字段列表 from1 [inner] join2 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 字段列表 from1 left [outer] join2 on 连接条件...;-- 右外连接语法
select 字段列表 from1 right [outer] join2 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、多表查询案例 多表查询有两大类&#xff1a;连接查询和子查询。 连接查询又分为隐式/显式内连接和左/右外连接。 子查询又分为标量子查询、列子查询、行子查询…...

RocketMQ 过滤消息 基于tag过滤和SQL过滤

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

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 提供了丰富的内置函数&#xff0c;涵盖了字符串处理、数值计算、日期时间操作、聚合分析以及控制流等多个方面。这些函数可以帮助用户更高效地进行数据查询和处理。 1.字符串函数 MySQL 提供了丰富的字符串函数来帮助用户处理和操作字符串数据。下面是一些常用的 MySQL…...

【蓝桥杯每日一题】扫雷

扫雷 知识点 2024-12-3 蓝桥杯每日一题 扫雷 dfs &#xff08;bfs也是可行的&#xff09; 题目大意 在一个二维平面上放置这N个炸雷&#xff0c;每个炸雷的信息有$(x_i,y_i,r_i) $&#xff0c;前两个是坐标信息&#xff0c;第三个是爆炸半径。然后会输入M个排雷火箭&#xff0…...

【算法】棋盘覆盖问题源代码及精简版

目录 一、题目 二、样例 三、示例代码 四、精简代码 五、总结 对于棋盘覆盖问题的解答和优化。 一、题目 输入格式&#xff1a; 第一行&#xff0c;一个整数n&#xff08;棋盘n*n&#xff0c;n确保是2的幂次&#xff0c;n<64&#xff09; 第二行&#xff0c;两个整数…...

Django的介绍

Django是一个高级的Python Web框架&#xff0c;它鼓励快速开发和干净、实用的设计。Django遵循MVC设计模式&#xff0c;即模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&#xff09;&#xff0c;并提供了一个即时可用的…...

【Spring工具插件】lombok使用和EditStarter插件

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 引入 一&#xff1a;lombok介绍 1&#xff1a;引入依赖 2&#xff1a;使用 3&#xff1a;原理 4&…...

掌控时间,成就更好的自己

在个人成长的道路上&#xff0c;时间管理是至关重要的一环。有效的时间管理能够让我们更加高效地完成任务&#xff0c;实现自己的目标&#xff0c;不断提升自我。 时间对每个人都是公平的&#xff0c;一天只有 24 小时。然而&#xff0c;为什么有些人能够在有限的时间里做出卓…...

Ruby On Rails 笔记2——表的基本知识

Active Record Basics — Ruby on Rails Guides Active Record Migrations — Ruby on Rails Guides 原文链接自取 1.Active Record是什么&#xff1f; Active Record是MVC模式中M的一部分&#xff0c;是负责展示数据和业务逻辑的一层&#xff0c;可以帮助你创建和使用Ruby…...

【AI系统】EfficientNet 系列

EfficientNet 系列 本文主要介绍 EffiicientNet 系列&#xff0c;在之前的文章中&#xff0c;一般都是单独增加图像分辨率或增加网络深度或单独增加网络的宽度&#xff0c;来提高网络的准确率。而在 EfficientNet 系列论文中&#xff0c;会介绍使用网络搜索技术(NAS)去同时探索…...

【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的!现在用Python写代码的人还多吗?

【Python小白|Python内置函数学习2】Python有哪些内置函数&#xff1f;不需要导入任何模块就可以直接使用的&#xff01;现在用Python写代码的人还多吗&#xff1f; 【Python小白|Python内置函数学习2】Python有哪些内置函数&#xff1f;不需要导入任何模块就可以直接使用的&a…...

蓝桥杯分治

P1226 【模板】快速幂 题目描述 给你三个整数 &#x1d44e;,&#x1d44f;,&#x1d45d;a,b,p&#xff0c;求 &#x1d44e;&#x1d44f; mod &#x1d45d;abmodp。 输入格式 输入只有一行三个整数&#xff0c;分别代表 &#x1d44e;,&#x1d44f;,&#x1d45d;a,b,p。…...

YOLOv8实战无人机视角目标检测

本文采用YOLOv8作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对无人机目标数据集进行训练和优化&#xff0c;该数据集包含丰富的无人机目标图像…...

三、【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的美妆购物网站

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

MySQL之创建和管理表

目录 1. MySQL中的数据类型​编辑​编辑 2. 创建和管理数据库 方式1&#xff1a;创建数据库 方式2&#xff1a;创建数据库并指定字符集 方式3&#xff1a;判断数据库是否已经存在&#xff0c;不存在则创建数据库&#xff08; 推荐 &#xff09; 总结 2.2 使用数据库 查看当…...

肌肉骨骼肿瘤治疗市场:潜力无限,未来可期

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

QGIS 创建三维渲染动画

打开数据包中的denali工程文档&#xff0c;可以看到DEM图层和山体阴影图层。首先创建彩色的山体阴影效果&#xff1a; 接下来新建3D视图&#xff1a; 配置三维地图 配置后&#xff0c;可用鼠标中键、右侧的操作盘等进行三维旋转等操作。 接下来在三维地图中创建动画效果&#x…...

Vue生成类似于打卡页面

数据表格 <el-table :data"tableData" border height"calc(100vh - 240px)" :cell-style"cellFun"><el-table-column label"姓名" show-overflow-tooltip prop"name" align"center"/><el-table-co…...

软件工程——期末复习(2)

Part1&#xff1a;软件工程基本概念 软件程序文档数据 在软件工程中&#xff0c;软件通常被定为程序、文档和数据的集合。程序是按事先设计的功能和性能要求编写的指令序列&#xff1b;程序是完成指定功能的一段特定语言代码。文档是描述程序操作和使用的文档&#xff0c;是与…...

vxe-table 键盘操作,设置按键编辑方式,支持覆盖方式与追加方式

vxe-table 全键盘操作&#xff0c;按键编辑方式设置&#xff0c;覆盖方式与追加方式&#xff1b; 通过 keyboard-config.editMode 设置按键编辑方式&#xff1b;支持覆盖方式编辑和追加方式编辑 安装 npm install vxe-pc-ui4.3.15 vxe-table4.9.15// ... import VxeUI from v…...

【BUG】VMware|vmrest正在运行此虚拟机,无法配置或删除快照

VMware版本&#xff1a;VMware 16 文章目录 省流版问题解决方案 详细解释版问题解决方案总结 省流版 问题 只读&#xff0c;因为vmrest正在运行虚拟机。 解决方案 参考&#xff1a;虚拟机设置&#xff0c;只读&#xff0c;因为vmrest正在运行此虚拟机。有谁遇到过这种问题吗&…...

STM32 串口和I2C结合案例:

需求 1. 电脑通过串口 给单机 下发点灯计划 例如 13322 单片机上的灯 LED1 亮1秒 灭1秒 LED3 亮1秒 灭1秒 LED3 亮一秒 灭1秒 133221332213322-> mian.c #include "usart1.h" #include "M24C02.h" #include "stdio.h" #include "le…...

QT6_UI设计——设置表格

环境&#xff1a;qt6.8 1、放置 双击 2行 、列 设置 3、设置表格内容 读取表格内容 uint16 get_table_value_16_cmd(int row,int column) {if(column<1)return 0;QTableWidgetItem *itemnew QTableWidgetItem;itemui1->tableWidget_2->item(row,column);if(item! nul…...

游戏使用辅助工具修改器检测不到游戏进程应该如何解决?多种解决方法分享

当您在使用游戏辅助工具或修改器时遇到“未检测到游戏进程”的提示&#xff0c;这通常意味着修改器未能正确识别并连接到游戏的运行实例。以下是一些可能的解决方案&#xff1a; 1. 确保游戏已启动&#xff1a;•确认游戏已经完全启动并且正在运行中。有时游戏可能还在加载界面…...

Java JVM(内存结构,垃圾回收,类加载,内存模型)

一、JVM 主要功能 1. 什么是 jvm&#xff1f; JVM&#xff08;Java Virtual Machine)&#xff1a;负责运行 Java 程序的核心组件。它将 Java 字节码&#xff08;.class 文件&#xff09;解释或编译为机器代码&#xff0c;并提供内存管理、垃圾回收和线程管理等功能。 JRE (J…...

C++设计模式(桥接、享元、外观、状态)

一、桥接模式 1.定义 将抽象部分与它的实现部分分离&#xff0c;使它们可以独立地变化。 桥接模式通过使用组合关系而不是继承关系来实现解耦&#xff0c;从而提高系统的灵活性和可扩展性。 2.组成 抽象&#xff1a;定义抽象部分的接口&#xff0c;包含一个指向实现类的对象…...