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

四、表关系与复杂查询

一、表关系设计与约束

1. 表关系类型与实现

关系类型实现方式示例场景
一对一共享主键 或 外键唯一约束用户 ↔ 用户详细信息
一对多外键约束部门 ↔ 员工
多对多中间表 + 联合主键学生 ↔ 课程

2. 核心约束类型

-- 完整表创建示例(含约束)
CREATE TABLE employees (emp_id INT PRIMARY KEY AUTO_INCREMENT,      -- 主键约束emp_name VARCHAR(50) NOT NULL,              -- 非空约束email VARCHAR(100) UNIQUE,                  -- 唯一约束dept_id INT,salary DECIMAL(10,2) CHECK (salary > 0),    -- 检查约束(MySQL 8.0+)FOREIGN KEY (dept_id) REFERENCES departments(dept_id) -- 外键约束
);
约束类型详解
约束类型作用注意事项
PRIMARY KEY唯一标识记录,自动创建聚集索引每表只能有一个主键
FOREIGN KEY强制引用完整性可能影响性能,高并发慎用
UNIQUE保证字段值唯一可空字段允许存在多个NULL值
CHECK自定义验证规则MySQL 8.0前需通过触发器实现
NOT NULL禁止空值与DEFAULT配合使用更安全

二、索引与查询优化

1. 索引的作用与类型

索引类型特点适用场景
B-Tree索引默认索引,支持范围查询大多数场景(如WHERE、ORDER BY)
唯一索引强制字段值唯一身份证号、邮箱等字段
联合索引多列组合索引常一起查询的字段组合

2. 索引创建与使用

-- 创建索引
CREATE INDEX idx_emp_name ON employees(emp_name);  -- 单列索引
CREATE UNIQUE INDEX idx_email ON employees(email);-- 唯一索引
CREATE INDEX idx_dept_salary ON employees(dept_id, salary); -- 联合索引-- 查看索引
SHOW INDEX FROM employees;-- 删除索引
DROP INDEX idx_emp_name ON employees;

3. 索引优化原则

  1. 最左前缀原则:联合索引 (A,B,C) 可生效于:

    • WHERE A=1
    • WHERE A=1 AND B=2
    • WHERE A=1 AND B=2 AND C=3
  2. 避免过度索引:索引会降低写操作速度

  3. 覆盖索引:查询字段全部在索引中时,无需回表

    -- 使用覆盖索引
    SELECT emp_name FROM employees WHERE emp_name LIKE '张%';
    

三、高级关联查询

1. JOIN 执行原理

-- 示例:三表关联
-- 查询部门名称、员工姓名及其领导的项目名称
SELECT d.dept_name,        -- 选择部门名称e.emp_name,         -- 选择员工姓名p.project_name      -- 选择项目名称
FROM departments d      -- 从部门表开始查询
JOIN employees e        -- 连接员工表ON d.dept_id = e.dept_id  -- 连接条件:部门ID匹配
LEFT JOIN projects p    -- 左连接项目表ON e.emp_id = p.leader_id;  -- 连接条件:员工ID与项目领导ID匹配
JOIN 执行顺序
  1. 执行 FROM departments d
  2. 执行 JOIN employees e → 生成中间结果集
  3. 执行 LEFT JOIN projects p → 扩展结果集
  4. 应用 WHERE 过滤(如果有)
  5. 执行 SELECT 字段投影

2. 自连接(Self Join)

-- 查询在同一部门中的不同员工对
SELECT e1.emp_name AS employee1,  -- 选择第一个员工的姓名e2.emp_name AS employee2   -- 选择第二个员工的姓名
FROM employees e1              -- 从员工表(别名 e1)开始查询
JOIN employees e2              -- 自连接员工表(别名 e2)ON e1.dept_id = e2.dept_id   -- 连接条件:部门ID相同AND e1.emp_id < e2.emp_id;   -- 确保员工ID不同且避免重复配对

3. 递归查询(WITH RECURSIVE)

-- 使用递归CTE生成从1到10的数字序列
WITH RECURSIVE numbers(n) AS (  -- 定义递归CTE,命名为numbers,包含列nSELECT 1                    -- 初始查询:从1开始UNION ALL                   -- 递归部分:将结果与后续查询合并SELECT n+1 FROM numbers     -- 递归查询:每次将n的值加1WHERE n < 10                -- 递归终止条件:n小于10时继续递归
)
SELECT * FROM numbers;          -- 最终查询:返回递归CTE的结果

四、综合案例:电商系统优化

1. 带约束的表设计

--产品表(products)
CREATE TABLE products (product_id INT PRIMARY KEY AUTO_INCREMENT,  -- 产品ID,主键,自增product_name VARCHAR(255) NOT NULL,    -- 产品名称,必填price DECIMAL(10,2) CHECK (price >= 0),    -- 产品价格,必须大于等于0stock INT DEFAULT 0 CHECK (stock >= 0)    -- 库存数量,默认值为0,必须大于等于0
);CREATE TABLE orders (order_id INT PRIMARY KEY AUTO_INCREMENT,    -- 订单ID,主键,自增user_id INT NOT NULL,    -- 用户ID,必填,外键关联用户表order_date DATETIME DEFAULT CURRENT_TIMESTAMP,    -- 订单日期,默认值为当前时间status ENUM('pending', 'shipped', 'completed') DEFAULT 'pending',    -- 订单状态,枚举类型,默认值为'pending'FOREIGN KEY (user_id) REFERENCES users(user_id)    -- 外键约束,关联用户表的user_id字段
);-- 中间表(含联合主键)
CREATE TABLE order_items (order_id INT,    -- 订单ID,联合主键之一,外键关联订单表product_id INT,    -- 产品ID,联合主键之一,外键关联产品表quantity INT CHECK (quantity > 0),    -- 购买数量,必须大于0PRIMARY KEY (order_id, product_id),    -- 联合主键,由order_id和product_id组成FOREIGN KEY (order_id) REFERENCES orders(order_id),    -- 外键约束,关联订单表的order_id字段FOREIGN KEY (product_id) REFERENCES products(product_id)    -- 外键约束,关联产品表的product_id字段
);

2. 索引优化实战

-- 高频查询:按用户和状态查订单
CREATE INDEX idx_user_status ON orders(user_id, status);-- 高频搜索:商品名称模糊查询
CREATE FULLTEXT INDEX idx_product_name ON products(product_name);-- 使用全文索引查询
SELECT * FROM products 
WHERE MATCH(product_name) AGAINST('手机 -配件' IN BOOLEAN MODE);

3. 复杂业务查询

-- 统计每个用户的2023年度消费总金额(包含未消费用户)
SELECT u.user_name,                             -- 用户姓名--当SUM的结果为NULL时,COALESCE会返回0COALESCE(SUM(oi.quantity * p.price), 0) AS total_spent  -- 计算消费总金额(未消费显示0)
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id          -- 关联用户和订单表(保留未下单用户)
LEFT JOIN order_items oi ON o.order_id = oi.order_id  -- 关联订单和订单明细表
LEFT JOIN products p ON oi.product_id = p.product_id  -- 关联订单明细和商品表
WHERE o.order_date BETWEEN '2023-01-01' AND '2023-12-31'  -- 筛选2023年订单
GROUP BY u.user_id;                          -- 按用户ID分组汇总消费金额-- 查找库存紧张的热销商品(销量TOP 10且库存<100)
SELECT p.product_name,                         -- 商品名称SUM(oi.quantity) AS total_sold,         -- 统计商品总销量p.stock                                 -- 显示当前库存量
FROM products p
JOIN order_items oi ON p.product_id = oi.product_id  -- 关联商品和订单明细表
GROUP BY p.product_id                       -- 按商品ID分组统计销量
HAVING total_sold > 100 AND stock < 100     -- 筛选销量>100且库存<100的商品
ORDER BY total_sold DESC                    -- 按销量降序排列
LIMIT 10;                                   -- 仅显示销量最高的前10条记录

五、常见错误与调试技巧

1. 外键约束冲突

错误示例

-- 尝试删除有子记录的部门
DELETE FROM departments WHERE dept_id = 1;
-- 报错:Cannot delete or update a parent row: a foreign key constraint fails

解决方案

-- 方法1:先删除子记录
DELETE FROM employees WHERE dept_id = 1;
DELETE FROM departments WHERE dept_id = 1;-- 方法2:使用级联删除(设计表时定义)
CREATE TABLE employees (...FOREIGN KEY (dept_id) REFERENCES departments(dept_id)ON DELETE CASCADE
);

2. 索引失效场景

场景示例优化方案
对索引列使用函数WHERE YEAR(create_time)=2023改为范围查询:WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
使用前导通配符模糊查询WHERE name LIKE '%张三%'使用全文索引或倒序存储
隐式类型转换WHERE id = '100'(id为INT)保持类型一致:WHERE id = 100

六、实战练习建议

1. 设计医院管理系统

  • 核心表:患者表、医生表、科室表、预约记录表、病历表
  • 要求
    1. 实现多对多关系(医生-科室)
    2. 添加合理的约束(如预约时间不能早于当前时间)
    3. 创建必要的索引
    4. 编写以下查询:
      • 查找某科室最繁忙的医生
      • 统计各科室的预约成功率
      • 检索患者的完整就诊历史

2. 性能优化挑战

  1. 对已有慢查询进行 EXPLAIN 分析
  2. 通过索引优化将查询时间从 2s 降至 200ms 以内
  3. 使用 FORCE INDEX 强制使用特定索引对比效果

相关文章:

四、表关系与复杂查询

一、表关系设计与约束 1. 表关系类型与实现 关系类型实现方式示例场景一对一共享主键 或 外键唯一约束用户 ↔ 用户详细信息一对多外键约束部门 ↔ 员工多对多中间表 联合主键学生 ↔ 课程 2. 核心约束类型 -- 完整表创建示例&#xff08;含约束&#xff09; CREATE TABLE…...

Qt 中,**信号与槽(Signals Slots)机制

在 Qt 中&#xff0c;信号与槽&#xff08;Signals & Slots&#xff09;机制 是实现对象间通信的核心模式&#xff0c;通常也被视为一种高效的“通知者模式”。它允许对象在特定事件发生时通知其他对象&#xff0c;且完全解耦。 核心概念 信号&#xff08;Signal&#xff0…...

Javaweb后端数据库多表关系一对多,外键,一对一

多表关系 一对多 多的表里&#xff0c;要有一表里的主键 外键 多的表上&#xff0c;添加外键 一对一 多对多 案例...

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务 在现代应用程序中&#xff0c;全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统&#xff0c;还是数据分析平台&#xff0c;快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎…...

VScode在Windows11中配置MSVC

因为MSVC编译器在vs当中&#xff0c;所以我们首先要安装vs的一部分组件。如果只是需要MSVC的话&#xff0c;工作负荷一个都不需要勾选&#xff0c;在单个组件里面搜索MSVC和windows11 SDK&#xff0c;其中一个是编译器&#xff0c;一个是头文件然后右下角安装即可。搜索Develop…...

【洛谷贪心算法题】P2240部分背包问题

【解题思路】 贪心策略选择 对于部分背包问题&#xff0c;关键在于如何选择物品放入背包以达到最大价值。由于物品可以分割&#xff0c;遍历排序后的物品数组&#xff0c;根据物品重量和背包剩余容量的关系&#xff0c;决定是将整个物品放入背包还是分割物品放入背包&#xff…...

DevOps原理和实现面试题及参考答案

解释 DevOps 的核心目标与文化价值观,如何理解 “CAMS” 模型? DevOps 的核心目标是打破开发(Development)和运维(Operations)之间的壁垒,通过自动化、协作和持续反馈,实现软件的快速、可靠交付,以更好地满足业务需求和客户期望。具体来说,DevOps 旨在缩短软件的交付…...

《Somewhat Practical Fully Homomorphic Encryption》笔记 (BFV 源于这篇文章)

文章目录 一、摘要二、引言1、FHE 一般分为三个逻辑部分2、噪声的管理3. 贡献点4. 文章思路 三、基础数学知识四、基于 RLWE 的加密1. LWE 问题2. RLWE 问题3. RLWE 问题的难度和安全性 五、加密方案1. LPR.ES 加密方案2. Lemma 1 (引理 1)3. Optimisation/Assumption 1 (优化/…...

SpringBoot 2 后端通用开发模板搭建(异常处理,请求响应)

目录 一、环境准备 二、新建项目 三、整合依赖 1、MyBatis Plus 数据库操作 2、Hutool 工具库 3、Knife4j 接口文档 4、其他依赖 四、通用基础代码 1、自定义异常 2、响应包装类 3、全局异常处理器 4、请求包装类 5、全局跨域配置 补充&#xff1a;设置新建类/接…...

DeepSeek本地部署与Dify结合创建私有知识库指南

python调用本地deepseek+Dify的API使用--测试WX自动发送信息-CSDN博客 DeepSeek,一家在人工智能领域具有显著技术实力的公司,凭借其千亿参数规模的AI大模型,以及仅需0.5元人民币即可进行百万tokens的API调用成本,已经取得了令人瞩目的成就。不仅如此,DeepSeek的模…...

Nginx 报错:413 Request Entity Too Large

做web开发时&#xff0c;对于上传附件的功能&#xff0c;如果nginx没有调整配置&#xff0c;上传大一点的文件就会发生下面这种错误&#xff1a; 要解决上面的问题&#xff0c;只需要调整Nginx配置文件中的 client_max_body_size 参数即可&#xff0c;这个配置参数一般在http配…...

Arduino项目实战:使用MQ-2气体传感器与OLED屏幕监测环境气体

概述 在这个项目中,MQ-2气体传感器是一个多功能的气体检测设备,能够感知多种常见气体,如甲烷、丁烷、丙烷、酒精和烟雾等。你可以把它想象成一个超级灵敏的“嗅觉”,能够帮助你实时检测环境中的各种有害气体。与Arduino板连接后,MQ-2传感器把捕捉到的气体浓度数据传送给A…...

泛微Ecode新增Button调用服务器中的JSP页面里的方法

前言 前端Ecode调用 后端接口编写 JSP文件方法 总结 前言 因为我们是从之前E8版本升级到E9的&#xff0c;所以会有一些接口是通过jsp文件来实现前后端调用的&#xff0c;这里介绍的就是如果你有接口是写在jsp文件里面调用的&#xff0c;但是你又想在Ecode中调用的对应的接…...

C#实现本地Deepseek模型及其他模型的对话

前言 1、C#实现本地AI聊天功能 WPFOllamaSharpe实现本地聊天功能,可以选择使用Deepseek 及其他模型。 2、此程序默认你已经安装好了Ollama。 在运行前需要线安装好Ollama,如何安装请自行搜索 Ollama下载地址&#xff1a; https://ollama.org.cn Ollama模型下载地址&#xf…...

【ESP32S3接入讯飞在线语音识别】

视频地址: 【ESP32S3接入讯飞在线语音识别】 1. 前言 使用Seeed XIAO ESP32S3 Sense开发板接入讯飞实现在线语音识别。自带麦克风模块用做语音输入,通过串口发送字符“1”来控制数据的采集和上传。 语音识别对比 平台api教程评分百度...

【51单片机】快速入门

动手实践 > 理论空谈&#xff01;从点亮LED开始&#xff0c;逐步扩展功能&#xff0c;2周可入门基础。 一、51单片机基础概念 什么是51单片机&#xff1f; 基于Intel 8051架构的8位微控制器&#xff0c;广泛用于嵌入式开发。 核心特性&#xff1a;4KB ROM、128B RAM、32个…...

leetcode707----设计链表【链表增删改打印等操作】

目录 一、题目介绍 二、单链表 2.1 创建链表类 2.1.1 定义链表节点结构体代码块 2.1.2 MyLinkedList类的构造函数 2.1.3 私有成员变量 2.2 接口1&#xff1a;获取第下标为index的节点的值 2.3 接口2&#xff1a;头部插入节点 2.4 接口3&#xff1a;尾部插入节点 2.5 接…...

【问题记录】Go项目Docker中的consul访问主机8080端口被拒绝

【问题记录】Go项目Docker中的consul访问主机8080端口被拒绝 问题展示解决办法 问题展示 在使用docker中的consul服务的时候&#xff0c;通过命令行注册相应的服务&#xff08;比如cloudwego项目的demo_proto以及user服务&#xff09;失败。 解决办法 经过分析&#xff0c;是…...

【缓存】缓存雪崩与缓存穿透:高并发系统的隐形杀手

缓存雪崩与缓存穿透&#xff1a;高并发系统的隐形杀手 在高并发系统中&#xff0c;缓存是提升性能的重要手段。然而&#xff0c;缓存使用不当也会带来一系列问题&#xff0c;其中最常见的就是缓存雪崩和缓存穿透。这两个问题如果不加以解决&#xff0c;可能会导致系统崩溃&…...

网络协议 HTTP、HTTPS、HTTP/1.1、HTTP/2 对比分析

1. 基本定义 HTTP&#xff08;HyperText Transfer Protocol&#xff09; 应用层协议&#xff0c;用于客户端与服务器之间的数据传输&#xff08;默认端口 80&#xff09;。 HTTP/1.0&#xff1a;早期版本&#xff0c;每个请求需单独建立 TCP 连接&#xff0c;效率低。HTTP/1.1&…...

DeepSeek实现FunctionCalling调用API查询天气

什么是FunctionCalling Function Calling&#xff08;函数调用&#xff09;是大型语言模型&#xff08;如 OpenAI 的 GPT 系列&#xff09;提供的一种能力&#xff0c;允许模型在生成文本的过程中调用外部函数或工具&#xff0c;以完成更复杂的任务。通过 Function Calling&am…...

从 Spring Boot 2 升级到 Spring Boot 3 的终极指南

一、升级前的核心准备 1. JDK 版本升级 Spring Boot 3 强制要求 Java 17 及以上版本。若当前项目使用 Java 8 或 11&#xff0c;需按以下步骤操作&#xff1a; 安装 JDK 17&#xff1a;从 Oracle 或 OpenJDK 官网下载&#xff0c;配置环境变量&#xff08;如 JAVA_HOME&…...

C#设计模式深度解析:经典实现与现代演进 ——基于《设计模式》的.NET技术实践

一、设计模式与C#语言特性融合 C#凭借其面向对象特性、泛型、委托/事件、LINQ等能力&#xff0c;为设计模式提供了更优雅的实现方式。以下通过典型模式展现其技术融合&#xff1a; 1. 工厂方法模式 泛型约束 public interface IProduct<T> where T : new() {void O…...

原子性(Atomicity)和一致性(Consistency)的区别?

原子性&#xff08;Atomicity&#xff09;和一致性&#xff08;Consistency&#xff09;是数据库事务ACID特性中的两个核心概念&#xff0c;虽然它们密切相关&#xff0c;但解决的问题和侧重点完全不同。原子性关注事务的操作完整性&#xff0c;而一致性关注数据的逻辑正确性。…...

windows设置暂停更新时长

windows设置暂停更新时长 win11与win10修改注册表操作一致 &#xff0c;系统界面不同 1.打开注册表 2.在以下路径 \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 右键新建 DWORD 32位值&#xff0c;名称为FlightSettingsMaxPauseDays 根据需求填写数…...

【Kimi】自动生成PPT-并支持下载和在线编辑--全部免费

【Kimi】免费生成PPT并免费下载 用了好几个大模型&#xff0c;有些能生成PPT内容&#xff1b; 有些能生成PPT&#xff0c;但下载需要付费&#xff1b; 目前只有Kimi生成的PPT&#xff0c;能选择模板、能在线编辑、能下载&#xff0c;关键全部免费&#xff01; 一、用kimi生成PP…...

一款在手机上制作电子表格

今天给大家分享一款在手机上制作电子表格的&#xff0c;免费好用的Exce1表格软件&#xff0c;让工作变得更加简单。 1 软件介绍 Exce1是一款手机制作表格的办公软件&#xff0c;您可以使用手机exce1在线制作表格、工资表、编辑xlsx和xls表格文件等&#xff0c;还可以学习使用…...

【实战 ES】实战 Elasticsearch:快速上手与深度实践-1.3.1单节点安装(Docker与手动部署)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 10分钟快速部署Elasticsearch单节点环境1. 系统环境要求1.1 硬件配置推荐1.2 软件依赖 2. Docker部署方案2.1 部署流程2.2 参数说明2.3 性能优化建议 3. 手动部署方案3.1 安…...

7 天精通 DeepSeek 实操手册

挑战目标 从零基础开始&#xff0c;用 7 天时间&#xff0c;精通 DeepSeek 实操。 对零基础的同学来说&#xff0c;要全部完成这个挑战并不容易。因此&#xff0c;我们提供了每天的学习目标和实操任务&#xff0c;并提供三大锦囊助你一臂之力&#xff1a; 针对常见问题的解决…...

过滤器 二、过滤器详解

过滤器生命周期&#xff1a; init(FilterConfig)&#xff1a;在服务器启动时会创建Filter实例&#xff0c;并且每个类型的Filter只创建一个实例&#xff0c;从此不再创建&#xff01;在创建完Filter实例后&#xff0c;会马上调用init()方法完成初始化工作&#xff0c;这个方法…...