MySQL 多表操作与复杂查询:深入理解多表关系和高级查询

大家好!今天我们要深入探讨 MySQL 中两个非常重要的主题——多表操作复杂查询


一. 多表操作

什么是多表操作?

在实际应用中,数据通常分布在多个表中,需要通过多表操作来获取完整信息。比如,一个学生表和一个课程表之间的关系,我们需要通过多表操作来查询某个学生的选课情况。

核心内容:
  • 多表关系
  • 外键约束
  • 联合查询

1. 多表关系

一对一关系

一个表中的一条记录对应另一个表中的一条记录。例如,用户表和个人信息表之间可以是一对一的关系。

-- 用户表
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL UNIQUE,email VARCHAR(100) NOT NULL UNIQUE
);-- 个人信息表
CREATE TABLE user_profiles(user_id INT PRIMARY KEY,address VARCHAR(255),phone VARCHAR(20),FOREIGN KEY (user_id) REFERENCES users(id)
);
一对多关系

一个表中的一条记录对应另一个表中的多条记录。例如,订单表和用户表之间可以是一对多的关系。

-- 用户表
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL UNIQUE,email VARCHAR(100) NOT NULL UNIQUE
);-- 订单表
CREATE TABLE orders(id INT PRIMARY KEY AUTO_INCREMENT,order_number VARCHAR(50) NOT NULL,user_id INT,order_date DATE,FOREIGN KEY (user_id) REFERENCES users(id)
);
多对多关系

一个表中的多条记录对应另一个表中的多条记录。例如,学生表和课程表之间可以是多对多的关系。

-- 学生表
CREATE TABLE students(id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL
);-- 课程表
CREATE TABLE courses(id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL
);-- 学生选课表(中间表)
CREATE TABLE student_courses(student_id INT,course_id INT,score DECIMAL(5,2),PRIMARY KEY(student_id, course_id),FOREIGN KEY(student_id) REFERENCES students(id),FOREIGN KEY(course_id) REFERENCES courses(id)
);

注意:

  • 多对多关系需要通过中间表来实现。
  • 中间表包含两个外键,分别引用两个表的主键。

2. 外键约束

创建外键约束

外键约束用于建立表与表之间的关联关系,确保数据的完整性和一致性。

-- 创建订单表,包含订单ID、订单号、客户ID、订单日期字段
CREATE TABLE orders(id INT PRIMARY KEY AUTO_INCREMENT,order_number VARCHAR(50) NOT NULL,customer_id INT,order_date DATE,FOREIGN KEY (customer_id) REFERENCES customers(id)
);
验证外键约束的作用
-- 插入有效员工数据
INSERT INTO employees VALUES(1, '张三', 1), (2, '李四', 2);-- 插入无效员工数据(dept_id不存在)
INSERT INTO employees VALUES(3, '王五', 3); -- 会报错-- 删除被引用的部门
DELETE FROM departments WHERE id = 1; -- 会报错

注意:

  • 禁止插入无效的外键值。
  • 禁止删除被引用的父表记录。
  • 可以配置级联操作(如 ON DELETE CASCADE)。

3. 联合查询

交叉连接(CROSS JOIN)

返回两个表的笛卡尔积,即两个表中所有行的组合。

-- 交叉连接
SELECT * FROM departments CROSS JOIN employees;-- 或者
SELECT * FROM departments, employees;
内连接(INNER JOIN)

返回两个表中匹配条件的行。

-- 内连接
SELECT e.id, e.name, d.name AS dept_name, e.salary 
FROM employees e 
INNER JOIN departments d ON e.dept_id = d.id;
左外连接(LEFT JOIN)

返回左表中的所有行,以及右表中匹配条件的行。如果右表中没有匹配的行,则返回 NULL

-- 左外连接
SELECT e.id, e.name, d.name AS dept_name, e.salary 
FROM employees e 
LEFT JOIN departments d ON e.dept_id = d.id;
右外连接(RIGHT JOIN)

返回右表中的所有行,以及左表中匹配条件的行。如果左表中没有匹配的行,则返回 NULL

-- 右外连接
SELECT e.id, e.name, d.name AS dept_name, e.salary 
FROM employees e 
RIGHT JOIN departments d ON e.dept_id = d.id;

二. 复杂查询

什么是复杂查询?

复杂查询是指通过子查询、聚合函数、分组等手段进行的高级查询操作。它可以帮助我们从大量数据中提取所需的信息。

核心内容:
  • 子查询
  • 聚合函数
  • 分组查询

1. 子查询

基本子查询

嵌套在其他 SQL 语句中的查询。它可以返回单个值、多个值或表。

-- 标量子查询:查询工资高于平均工资的员工
SELECT * FROM employees WHERE salary > (SELECT AVG(salary) FROM employees
);-- 列子查询:查询技术部和市场部的员工
SELECT * FROM employees WHERE dept_id IN (SELECT id FROM departments WHERE name IN ('技术部', '市场部')
);
ALL 关键字

表示与子查询返回的所有值进行比较。

-- 查询工资高于所有市场部员工的员工
SELECT * FROM employees WHERE salary > ALL (SELECT salary FROM employees WHERE dept_id = (SELECT id FROM departments WHERE name = '市场部')
);
ANY/SOME 关键字

表示与子查询返回的任意一个值进行比较。

-- 查询工资高于市场部任意一个员工的员工
SELECT * FROM employees WHERE salary > ANY (SELECT salary FROM employees WHERE dept_id = (SELECT id FROM departments WHERE name = '市场部')
);
EXISTS 关键字

表示子查询是否返回结果集。

-- 查询有员工的部门
SELECT * FROM departments d WHERE EXISTS (SELECT * FROM employees e WHERE e.dept_id = d.id
);

2. 聚合函数

聚合函数用于统计、求和、平均值等操作。

-- 统计学生总数
SELECT COUNT(*) AS 学生总数 FROM students;-- 计算总成绩
SELECT SUM(score) AS 总成绩 FROM students;-- 最高分和最低分
SELECT MAX(score) AS 最高分, MIN(score) AS 最低分 FROM students;-- 按班级分组,统计每个班级的学生数量
SELECT class_id, COUNT(*) AS 学生数量 FROM students GROUP BY class_id;-- 按班级分组,计算每个班级的平均成绩
SELECT class_id, AVG(score) AS 平均成绩 FROM students GROUP BY class_id;-- 分组后筛选,只显示学生数量大于2的班级
SELECT class_id, COUNT(*) AS 学生数量 
FROM students 
GROUP BY class_id 
HAVING COUNT(*) > 2;

3. 自关联查询

自关联查询是指表与自身进行连接查询,通常用于处理层次结构数据。

-- 创建员工表,包含上级ID
CREATE TABLE employees(id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL,manager_id INT
);-- 插入数据
INSERT INTO employees VALUES (1, '张三', NULL), (2, '李四', 1), (3, '王五', 1), (4, '赵六', 2);-- 自关联查询,查询员工及其上级
SELECT e.name AS 员工, m.name AS 上级
FROM employees e 
LEFT JOIN employees m ON e.manager_id = m.id;

三. 总结与最佳实践

总结

操作类型说明
一对一关系一个表中的一条记录对应另一个表中的一条记录
一对多关系一个表中的一条记录对应另一个表中的多条记录
多对多关系一个表中的多条记录对应另一个表中的多条记录,需通过中间表实现
外键约束建立表与表之间的关联关系,确保数据的完整性和一致性
交叉连接返回两个表的笛卡尔积
内连接返回两个表中匹配条件的行
左外连接返回左表中的所有行,以及右表中匹配条件的行
右外连接返回右表中的所有行,以及左表中匹配条件的行
子查询嵌套在其他 SQL 语句中的查询
聚合函数用于统计、求和、平均值等操作
自关联查询表与自身进行连接查询

最佳实践

  • 合理使用多表关系:根据业务需求选择合适的关系类型。
  • 灵活运用联合查询:根据需求选择合适的连接方式。
  • 优化复杂查询性能:避免不必要的复杂查询,适当使用索引。

一句话总结:

多表操作帮助我们构建复杂的数据库模型,而复杂查询则是我们的“数据探索工具”,帮助我们在数据库中高效地获取所需信息。


结尾

通过这篇博客,我们详细讲解了 MySQL 中多表操作和复杂查询的核心概念和使用方法。

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

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

相关文章

Java入门级教程7——eclipse新建Maven项目,创建和连接数据库,创建数据库表

目录 1.若没有Maven项目,可以选择新建 2.添加Maven依赖 3.数据库的创建 3.1 新建连接 --> 创建数据库 3.2 创建数据库表 4.连接数据库 1.若没有Maven项目,可以选择新建 步骤一:点击 File --> New --> Project 步骤二&#xf…

请求库-axios

Axios 是一个基于 Promise 的 HTTP 客户端库,用于浏览器和 Node.js 环境。它支持发送异步 HTTP 请求,并提供了简洁的 API 来处理请求和响应。1、安装axios因为axios是一个第三方库,所以在使用之前我们需要先安装第三方模块。安装 Axios 需通过…

电子烟的4种屏幕驱动集成语音方案介绍

目前电子烟在全球市场的表现非常不错,很多国产电子烟厂家都有非常不错的产品,而屏幕驱动方案是电子烟智能化的重要组成部分,今天就给大家带来电子烟的4种主流屏幕驱动方案(含2025年最新版方案)。​  方案一、LED显示方案语音播报集成方案 W…

无法加载 DLL“xxxxxxx.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。

(无法加载 DLL“xxxxxxx.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。) 这个错误: 无法加载 DLL“ZH_P2P_Libx64.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E) 意味着你的程序在运行时试图加载一个名为 xxxxxxx.dll 的动态链接库&#…

Flask/Django 生产部署:Gunicorn vs Nginx,Windows 与 Linux 实战指引

Flask/Django 生产部署:Gunicorn vs Nginx,Windows 与 Linux 实战指引 TL;DR Gunicorn:Python WSGI 应用服务器,运行 Flask/Django(Linux 用)。Nginx:反向代理/网关(TLS、静态、限流…

Nginx 优化与防盗链全解析:从性能调优到资源保护

Nginx 优化与防盗链全解析:从性能调优到资源保护 文章目录Nginx 优化与防盗链全解析:从性能调优到资源保护一、基础安全优化:隐藏版本号1.1 查看当前版本号1.2 两种隐藏/修改方案方案一:修改配置文件(快速隐藏&#xf…

HOT100--Day20--39. 组合总和,22. 括号生成,79. 单词搜索

HOT100–Day20–39. 组合总和,22. 括号生成,79. 单词搜索 每日刷题系列。今天的题目是《力扣HOT100》题单。 题目类型:回溯。 关键:掌握排列,组合。记得回溯。可以重复选的话,下一层index从哪里开始&#x…

高并发场景下的“命令执行”注入绕道记

环境:CentOS 8 OpenResty 1.21 PHP-FPM 8.0 背景:营销团队上线了一个“图片裁剪”接口,参数直接拼进 shell_exec,结果被打成“矿机”。1. 发现:流量突增 30 倍,却不见数据库慢查询 iftop -i eth0出站 1.8…

【modbus学习】

Modbus通信(源于施耐德)串行链路:RTU(传输大量数据,适合工业)、ASCII(少量数据,适合计算机)TCP/IP:TCP(传输严谨,效率低)、…

Redis单线程模型为什么快?

Redis的单线程模型指的是redis只使用一个线程来出来所有的命令式指令,但是不是意味着redis内部就只使用一个线程来处理所有的任务。都知道redis是一个客户端-服务器的程序,那么redis就只有一个服务器,但是有多个客户端,就像mysql一…

前端安全攻防:XSS, CSRF 等常见威胁的防范与检测指南

在如今高度互联的 Web 应用世界里,前端安全不再是可有可无的选项,而是构建可信赖、健壮应用的基石。随着 Web 技术的发展,攻击者们也变得越来越狡猾,前端遭受的攻击手段层出不穷。其中,跨站脚本攻击 (XSS) 和跨站请求伪…

Scikit-learn Python机器学习 - 特征降维 压缩数据 - 特征选择 - 移除低方差特征(VarianceThreshold)

锋哥原创的Scikit-learn Python机器学习视频教程: 2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程主要讲解基于Scikit-learn的Python机器学习知识,包括机器学习概述,特征工程(数据…

C#(链表创建与原地反转)

链表创建(C#) 在C#中,链表可以通过自定义节点类实现。每个节点包含数据域和指向下一个节点的引用。 public class ListNode {public int val;public ListNode next;public ListNode(int val0, ListNode nextnull) {this.val val;this.next…

Android --- AOSP源码导入Android Studio

AOSP代码量庞大,为了开发的方便,我们需要导入到android studio中,其中关键的一 项就是配置跳转。尤其是对于Framework开发来说生成 ipr,iml 工程文件make idegen ./development/tools/idegen/idegen.sh会生成如下文件首先需要修改ipr和iml文件…

游戏中的设计模式——第一篇 设计模式简介

前言 对于设计模式,相信很多开发者并不陌生,我在学习过程中希望把自己的一些总结和心得体会与你分享。 本专栏主要将重点放在设计模式在游戏中的应用,会结合大家熟悉的游戏场景和功能阐述设计模式在该处应用的好处。因为设计模式很多&#xf…

SpringBoot + RustFS 实现文件切片极速上传技术

本文将手把手教你如何通过 SpringBoot 和 RustFS 构建高性能文件切片上传系统,解决大文件传输的痛点,实现秒传、断点续传和分片上传等高级功能。 目录 一、为什么选择 RustFS SpringBoot? 二、环境准备与部署 2.1 安装 RustFS 2.2 Sprin…

在Word和WPS文字中便捷切换英文段落大小写

在Word和WPS文字中编辑英文段落时,有时候英文字母的大小写不规范,或者需要把某一段全部改为大写字母怎么办?使用ShiftF3组合键即可快速在三种模式中切换:全部大写、全部小写、首字母大写——其中首字母大写的Word是每一句话的第一…

成都金牛区哪里租好办公室?国际数字影像产业园享税收优惠

在成都金牛区租赁优质办公室,国际数字影像产业园凭借其享有的税收优惠政策,成为了许多企业的首选之地。税收优惠对于租赁办公室的企业来说,是一笔不小的成本节省。国际数字影像产业园针对入驻企业提供的税收优惠政策,能在企业运营…

CSS `:is()` `:where()` 实战指南:简化选择器,提升可维护性

🎯 CSS :is() & :where() 实战指南:简化选择器,提升可维护性你是否在项目中写过一大串重复的选择器?比如: h1, h2, h3, h4, h5, h6 { margin-bottom: 1rem; }这样的代码既冗长又难维护。 现在 CSS 提供了 :is() 和…

Linux I/O 访问架构深入分析

Linux I/O 访问架构深入分析 目录 概述I/O 架构层次核心数据结构I/O 处理流程VFS 虚拟文件系统块设备I/O字符设备I/O内存映射I/O异步I/O机制I/O调度器调试工具与方法性能优化策略 概述 Linux I/O 系统是一个多层次、高度抽象的架构,旨在为应用程序提供统一的文件访问…