Mysql--基础篇--多表查询(JOIN,笛卡尔积)

在MySQL中,多表查询(也称为联表查询或JOIN操作)是数据库操作中非常常见的需求。通过多表查询,你可以从多个表中获取相关数据,并根据一定的条件将它们组合在一起。MySQL支持多种类型的JOIN操作,每种JOIN都有不同的用途和行为。

1、JOIN的基本概念

JOIN是一种用于从多个表中检索数据的操作。它允许你根据某些条件将两个或多个表中的行组合在一起。JOIN操作的核心思想是基于表之间的关联字段(通常是外键)来匹配行,并返回符合条件的结果集。

(1)、关联字段

  • 主键(Primary Key):唯一标识表中每一行的字段。
  • 外键(Foreign Key):一个表中的字段,引用另一个表的主键。外键用于建立表与表之间的关系。

(2)、JOIN类型

MySQL支持以下几种主要的JOIN类型:

  • 内连接(INNER JOIN):只返回两个表中满足连接条件的行。
  • 左连接(LEFT JOIN):返回左表中的所有行,即使右表中没有匹配的行,结果集中右表的列将填充为NULL。
  • 右连接(RIGHT JOIN):返回右表中的所有行,即使左表中没有匹配的行,结果集中左表的列将填充为NULL。
  • 全外连接(FULL OUTER JOIN):返回两个表中的所有行,无论是否满足连接条件。MySQL 不直接支持FULL OUTER JOIN,但可以通过UNION实现类似的效果。
  • 交叉连接(CROSS JOIN):返回两个表的笛卡尔积,即每个表中的每一行都与另一个表中的每一行组合。

2、JOIN的语法

(1)、内连接(INNER JOIN)

内连接是最常用的JOIN类型,它只返回两个表中满足连接条件的行。

示例:
假设我们有两个表employees和departments,其中employees表包含员工信息,departments表包含部门信息。employees表中的department_id字段是外键,引用了departments表的id字段。
sql:

-- 查询所有有部门的员工及其所属部门名称
SELECT employees.name, departments.name AS department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.id;

结果:
只返回那些有对应部门的员工信息。如果某个员工没有分配到任何部门,则该员工不会出现在结果集中。

(2)、左连接(LEFT JOIN)

左连接返回左表中的所有行,即使右表中没有匹配的行。对于右表中没有匹配的行,结果集中右表的列将填充为NULL。

示例:
查询所有员工及其所属部门名称,即使某些员工没有分配到部门
sql:

SELECT employees.name, departments.name AS department_name
FROM employees
LEFT JOIN departments ON employees.department_id = departments.id;

结果:
返回所有员工的信息。对于没有分配到部门的员工,department_name列将显示为NULL。

(3)、右连接(RIGHT JOIN)

右连接返回右表中的所有行,即使左表中没有匹配的行。对于左表中没有匹配的行,结果集中左表的列将填充为NULL。

示例:
查询所有部门及其员工,即使某些部门没有员工
sql:

SELECT employees.name, departments.name AS department_name
FROM employees
RIGHT JOIN departments ON employees.department_id = departments.id;

结果:
返回所有部门的信息。对于没有员工的部门,employees.name 列将显示为 NULL。

(4)、全外连接(FULL OUTER JOIN)

全外连接返回两个表中的所有行,无论是否满足连接条件。MySQL不直接支持FULL OUTER JOIN,但可以通过 UNION 实现类似的效果。

示例:
查询所有员工及其所属部门,以及所有部门及其员工
sql:

SELECT employees.name, departments.name AS department_name
FROM employees
LEFT JOIN departments ON employees.department_id = departments.id
UNION
SELECT employees.name, departments.name AS department_name
FROM employees
RIGHT JOIN departments ON employees.department_id = departments.id;

结果:
返回所有员工和部门的信息。对于没有分配到部门的员工,department_name列将显示为NULL;对于没有员工的部门,employees.name列将显示为NULL。

(5)、交叉连接(CROSS JOIN)

交叉连接返回两个表的笛卡尔积,即每个表中的每一行都与另一个表中的每一行组合。

示例:
查询所有员工与所有部门的组合
sql:

SELECT employees.name, departments.name AS department_name
FROM employees
CROSS JOIN departments;

结果:
返回每个员工与每个部门的组合,结果集的行数等于employees表的行数乘以 departments表的行数。
在这里插入图片描述

3、多表查询的高级用法

(1)、多表JOIN

你可以在一个查询中连接多个表。只需在FROM子句中依次添加多个JOIN语句即可。

示例:
假设我们有三个表:employees(员工表)、departments(部门表)和salaries(工资表)。我们希望查询每个员工的姓名、所属部门名称以及他们的工资。
sql:

SELECT employees.name, departments.name AS department_name, salaries.salary
FROM employees
INNER JOIN departments ON employees.department_id = departments.id
INNER JOIN salaries ON employees.id = salaries.employee_id;

结果:
返回每个员工的姓名、所属部门名称以及他们的工资。

(2)、自连接(Self Join)

自连接是指一个表与自身进行连接。这通常用于处理具有层次结构的数据,例如员工的上下级关系。

示例:
假设employees表中有一个manager_id字段,表示每个员工的上级领导。我们希望查询每个员工及其上级领导的姓名。
sql:

SELECT e1.name AS employee_name, e2.name AS manager_name
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.id;

结果:
返回每个员工及其上级领导的姓名。对于没有上级领导的员工,manager_name列将显示为NULL。

(3)、子查询(Subquery)

子查询是指在一个查询中嵌套另一个查询。子查询可以用于过滤、聚合等操作。

示例:
假设我们想查询工资高于平均工资的员工。
sql:

SELECT employees.name, salaries.salary
FROM employees
INNER JOIN salaries ON employees.id = salaries.employee_id
WHERE salaries.salary > (SELECT AVG(salary) FROM salaries);

结果:
返回工资高于平均工资的员工及其工资。

4、JOIN的性能优化

多表查询可能会对性能产生影响,尤其是在处理大量数据时。为了提高多表查询的性能,可以采取以下几种优化措施:

(1)、索引优化

  • 确保连接字段上有索引:在JOIN操作中,连接条件中的字段(如外键)应该有索引。索引可以显著提高查询的执行速度。

  • 覆盖索引:如果查询中涉及的列都在索引中,MySQL可以直接从索引中获取数据,而不需要访问实际的表数据。这种情况下,查询性能会大幅提升。

(2)、避免不必要的列

  • 只选择需要的列:在SELECT语句中,尽量只选择你需要的列,而不是使用 SELECT *。这样可以减少I/O操作,提升查询性能。

(3)、使用适当的JOIN类型

  • 选择合适的JOIN类型:根据业务需求选择合适的JOIN类型。例如,如果你只需要查询满足条件的行,使用INNER JOIN;如果你需要保留所有行,使用LEFT JOIN或RIGHT JOIN。

(4)、分页查询

  • 使用分页查询:如果你只需要查询部分数据,可以使用LIMIT和OFFSET进行分页查询,避免一次性加载大量数据。

示例:

SELECT employees.name, departments.name AS department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.id
LIMIT 10 OFFSET 0;

结果:
返回前 10 条记录。

(5)、EXPLAIN分析查询计划

  • 使用EXPLAIN分析查询计划:通过EXPLAIN关键字,可以查看MySQL如何执行查询,帮助你发现潜在的性能问题。EXPLAIN会显示查询的执行计划,包括使用的索引、扫描的行数等信息。

示例:

EXPLAIN SELECT employees.name, departments.name AS department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.id;

结果:
返回查询的执行计划,帮助你分析查询的性能瓶颈。

5、常见问题及解决方案

(1)、笛卡尔积问题

  • 问题描述:如果不指定连接条件,JOIN操作可能会导致笛卡尔积,即每个表中的每一行都与另一个表中的每一行组合,结果集的行数可能非常大。

  • 解决方案:始终确保在JOIN操作中指定明确的连接条件,避免笛卡尔积的发生。

(2)、N+1查询问题

  • 问题描述:是指在执行一次查询后,又触发了多个额外的查询,导致查询次数大幅增加,影响数据库性能。这种情况通常发生在ORM(对象关系映射)框架中。如获取所有人员所在部门信息,N+1问题就是:先查询主表中所有的人员,在遍历所有人员去查询部门表。

  • 解决方案:使用JOIN进行批量查询:将主表和子表的数据一次性查询出来,避免N+1造成多次查询问题。

(3)、重复数据问题

  • 问题描述:在某些复杂的JOIN操作中,可能会出现重复数据。例如,当一个表中有多个匹配的行时,结果集中可能会出现重复的记录。

  • 解决方案:使用DISTINCT关键字去除重复数据,或者调整JOIN条件,确保结果集中没有重复的行。

示例:

SELECT DISTINCT employees.name, departments.name AS department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.id;

结果:
返回不重复的员工及其所属部门名称。

6、总结

  • JOIN是MySQL中用于从多个表中检索数据的强大工具。通过不同的JOIN类型(如INNER JOIN、LEFT JOIN、RIGHT JOIN等),你可以根据业务需求灵活地组合多个表的数据。
  • 性能优化是多表查询中不可忽视的一部分。通过合理的索引设计、选择合适的JOIN类型、避免不必要的列以及使用EXPLAIN分析查询计划,可以显著提升查询的性能。
  • 常见问题(如笛卡尔积、N+1查询、重复数据等)需要特别注意,并采取相应的解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/505841.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gesp(C++四级)(11)洛谷:B4005:[GESP202406 四级] 黑白方块

gesp(C四级)(11)洛谷:B4005:[GESP202406 四级] 黑白方块 题目描述 小杨有一个 n n n 行 m m m 列的网格图,其中每个格子要么是白色,要么是黑色。对于网格图中的一个子矩形,小杨认为它是平衡的…

易于上手难于精通---关于游戏性的一点思考

1、小鸟、狙击、一闪,都是通过精准时机来逼迫玩家练习, 而弹道、出招时机等玩意,不是那么容易掌握的,需要反复的观察、反应与行动, 这也正是游戏性的体现, 玩家能感觉到一些朦胧的东西,但又不…

微信小程序——创建滑动颜色条

在微信小程序中,你可以使用 slider 组件来创建一个颜色滑动条。以下是一个简单的示例,展示了如何实现一个颜色滑动条,该滑动条会根据滑动位置改变背景颜色。 步骤一:创建小程序项目 首先,使用微信开发者工具创建一个新…

JVM实战—12.OOM的定位和解决

大纲 1.如何对系统的OOM异常进行监控和报警 2.如何在JVM内存溢出时自动dump内存快照 3.Metaspace区域内存溢出时应如何解决(OutOfMemoryError: Metaspace) 4.JVM栈内存溢出时应如何解决(StackOverflowError) 5.JVM堆内存溢出时应该如何解决(OutOfMemoryError: Java heap s…

Unity自定义编辑器:基于枚举类型动态显示属性

1.参考链接 2.应用 target并设置多选编辑 添加[CanEditMultipleObjects] using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor;[CustomEditor(typeof(LightsState))] [CanEditMultipleObjects] public class TestInspector :…

Qt重写webrtc的demo peerconnection

整个demo为: 可以选择多个编码方式: cmake_minimum_required(VERSION 3.5)project(untitled LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON)set(CMA…

IOS HTTPS代理抓包工具使用教程

打开抓包软件 在设备列表中选择要抓包的 设备,然后选择功能区域中的 HTTPS代理抓包。根据弹出的提示按照配置文件和设置手机代理。如果是本机则会自动配置,只需要按照提醒操作即可。 iOS 抓包准备 通过 USB 将 iOS 设备连接到电脑,设备需解…

《机器学习》——支持向量机(SVM)

文章目录 什么是支持向量机?基本原理数学模型 支持向量机模型模型参数属性信息 支持向量机实例(1)实例步骤读取数据可视化原始数据使用支持向量机训练可视化支持向量机结果完整代码 支持向量机实例(2)实例步骤导入数据…

高级软件工程-复习

高级软件工程复习 坐标国科大,下面是老师说的考试重点。 Ruby编程语言的一些特征需要了解要能读得懂Ruby程序Git的基本命令操作知道Rails的MVC工作机理需要清楚,Model, Controller, View各司什么职责明白BDD的User Story需要会写,SMART要求能…

使用 Maxwell 计算母线的电动势

三相短路事件的动力学 三相短路事件在电气系统中至关重要,因为三相之间的意外连接会导致电流大幅激增。如果管理不当,这些事件可能会造成损坏,因为它们会对电气元件(尤其是母线)产生极大的力和热效应。 短路时&#x…

Github出现复杂问题 无法合并 分支冲突太多 如何复原

目录 问题再现 解决思路 当然我所指的是在 main 分支开一个新的分支 删除本地文件夹 重新克隆 开一个新分支 切换分支 下载远程分支 文件覆盖 合并到主分支 ​​​​​​​问题再现 太复杂了 无法更改 编译器现状 全部崩溃了 无法更改 即使创建一个新的分支也无济于…

Jenkins触发器--在其他项目执行后构建

前言: jenkins中有多种触发器可用,可以方便的控制构建的启动 这里简单介绍下项目后构建的配置方法 1. 解释: Build after other projects are built Set up a trigger so that when some other projects finish building, a new build is…

CI/CD 流水线

CI/CD 流水线 CI 与 CD 的边界CI 持续集成CD(持续交付/持续部署)自动化流程示例: Jenkins 引入到 CI/CD 流程在本地或服务器上安装 Jenkins。配置 Jenkins 环境流程设计CI 阶段:Jenkins 流水线实现CD 阶段:Jenkins 流水…

计算机毕业设计Python机器学习农作物健康识别系统 人工智能 图像识别 机器学习 大数据毕业设计 算法

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

计算机网络之---物理层设备

什么是物理层设备 物理层设备是指负责数据在物理媒介上传输的硬件设备,它们主要处理数据的转换、信号的传输与接收,而不涉及数据的内容或意义。常见的物理层设备包括网卡、集线器、光纤收发器、调制解调器等。 物理层设备有哪些 1、网卡(N…

HTML实战课堂之简单的拜年程序

一、目录:  一、目录: 二、祝福 三:代码讲解 (1)详细解释: 1.HTML部分 2. CSS部分 三、运行效果(随机截图): 四、完整代码: 二、祝福…

【数据库系统概论】数据库恢复技术

目录 11.1 事务的基本概念 事务的定义 事务的开始与结束 事务的ACID特性 破坏ACID特性的因素 11.2 数据库恢复概述 11.3 故障的种类 1. 事务内部的故障 2. 系统故障 3. 介质故障 4. 计算机病毒 11.4 恢复的实现技术 如何建立冗余数据 数据转储 登记日志文件 11…

Ubuntu问题 -- 硬盘存储不够了, 如何挂载一个新的硬盘上去, 图文简单明了, 已操作成功

需求 我现在有一个ubuntu22.04操作系统的服务器, 但是当前硬盘不够用了, 我买了一个1T的SSD固态硬盘, 且已经安装在服务器上了, 我需要将这个硬盘挂载到当前ubuntu的某个目录上 开始 1. 确认新硬盘是否被系统识别 打开终端,输入以下命令查看系统识别到的硬盘&…

Linux第一个系统程序---进度条

进度条---命令行版本 回车换行 其实本质上回车和换行是不同概念,我们用一张图来简单的理解一下: 在计算机语言当中: 换行符:\n 回车符:\r \r\n:回车换行 这时候有人可能会有疑问:我在学习C…

JavaSE——网络编程

一、InetAddress类 InetAddress是Java中用于封装IP地址的类。 获取本机的InetAddress对象: InetAddress localHost InetAddress.getLocalHost();根据指定的主机名获取InetAddress对象(比如说域名) InetAddress host InetAddress.getByNa…