Mysql基础-多表查询(详细版)
目录
- 一、表的关系类型与适用场景
- 二、连接方式与使用场景
- 三、易错点与注意事项
- 四、总结
一、表的关系类型与适用场景
1. 一对一关系
场景:一个表的记录对应另一个表的唯一记录
案例:用户表 + 用户详情表
CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE user_details (user_id INT PRIMARY KEY,address VARCHAR(100),FOREIGN KEY (user_id) REFERENCES users(id)
);
2. 一对多关系
场景:主表的一条记录对应从表的多条记录
案例:部门表 + 员工表
CREATE TABLE departments (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE employees (id INT PRIMARY KEY,name VARCHAR(50),dept_id INT,FOREIGN KEY (dept_id) REFERENCES departments(id)
);
3. 多对多关系
场景:两个表的记录可以相互对应多条记录
案例:学生表 + 课程表(通过中间表实现)
CREATE TABLE students (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE courses (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE student_courses (student_id INT,course_id INT,PRIMARY KEY (student_id, course_id),FOREIGN KEY (student_id) REFERENCES students(id),FOREIGN KEY (course_id) REFERENCES courses(id)
);
二、连接方式与使用场景
1. 内连接(INNER JOIN)
场景:需要两表同时存在匹配记录的数据,相当于查询的是两张表的交集,不能查空。
-- 查询所有有部门的员工信息
SELECT e.name, d.name AS dept_name
FROM employees e
INNER JOIN departments d
ON e.dept_id = d.id;--等价写法(这种写法平时项目里用的更多)
SELECT e.name, d.name AS dept_name
FROM employees e,departments d
ON e.dept_id = d.id;
2. 左外连接(LEFT JOIN)
场景:保留左表所有记录,右表无匹配时显示NULL(相比右外,实际开发用的更多)
相当于查询的是两张表的交集,但是能查空
-- 查询所有员工(包括未分配部门的)
SELECT e.name, d.name AS dept_name
FROM employees e
LEFT JOIN departments d
ON e.dept_id = d.id;
--两表出现相同字段要起别名
3. 右外连接(RIGHT JOIN)
场景:保留右表所有记录,左表无匹配时显示NULL
-- 查询所有部门(包括没有员工的)
SELECT d.name AS dept_name, e.name
FROM employees e
RIGHT JOIN departments d
ON e.dept_id = d.id;
补充对比示例说明:
假设有以下两个表:
员工表 (employees)
| id | name | dept_id |
|---|---|---|
| 1 | 张三 | 101 |
| 2 | 李四 | NULL |
部门表 (departments)
| id | dept_name |
|---|---|
| 101 | 技术部 |
| 102 | 市场部 |
不同连接的结果差异:
-- 内连接(INNER JOIN)
SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;
-- 结果:只有张三 + 技术部-- 左连接(LEFT JOIN)
SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.id;-- 结果:
-- 张三 + 技术部
-- 李四 + NULL
❗ 关键区别:
-
连接类型 是否要求右表有数据 是否保留左表所有数据 典型场景 INNER JOIN 必须 否 查询「完整关联信息」 LEFT JOIN 不必须 是 查询「左表全部+右表能关联的部分」
🧠 易错点提醒:
-
不要混淆「存在数据」和「匹配条件」
- 即使两表都有数据,但若 不满足连接条件,内连接也会过滤掉
- 例如:员工表有
dept_id=100,部门表没有id=100的记录时,该员工不会出现在内连接结果中
-
默认 JOIN 行为差异
-- 以下两种写法等价 SELECT * FROM A INNER JOIN B ON A.id = B.a_id;--显式内连接 SELECT * FROM A, B WHERE A.id = B.a_id; -- 隐式内连接
4. 全外连接/联合查询(FULL OUTER JOIN)
场景:同时保留两表所有记录(MySQL会用到关键字 union或union all)
对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
--将薪资低于5000的员工,和年龄大于50的员工全部查询出来。
--union all 包含重复数据
select * from emp where salary < 5000
union all
select * from emp where age > 50;
--union 去除重复数据
select*fromemp where salary< 5000
union
select * from emp where age > 50;
tip: 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
union all会将全部的数据直接合并在一起,union会对合并之后的数据去重。
5. 交叉连接(CROSS JOIN)
场景:生成笛卡尔积,常用于组合场景
-- 生成颜色与尺寸的所有组合
SELECT colors.name, sizes.name
FROM colors
CROSS JOIN sizes;
6. 自连接(SELF JOIN)
场景:同一表内数据关联查询
tip:自连接一定要起别名
-- 查找员工的上级经理
SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m
ON e.manager_id = m.id;
三、易错点与注意事项
-
忘记关联条件导致笛卡尔积
-- 错误!缺少ON条件,将产生百万级数据 SELECT * FROM employees, departments; -
NULL值处理问题
-- 外连接后过滤条件应放在ON子句 SELECT * FROM A LEFT JOIN B ON A.id = B.a_id AND B.status = 1; -- ✔ 正确写法 -
多次连接时的别名冲突
-- 必须为每个表指定唯一别名 SELECT o.order_no, c1.name AS city_from, c2.name AS city_to FROM orders o LEFT JOIN cities c1 ON o.from_city = c1.id LEFT JOIN cities c2 ON o.to_city = c2.id; -
连接顺序影响性能
-- 大表在前可能导致性能问题 SELECT * FROM huge_table -- ✘ 大表在前 INNER JOIN small_table ON ...
四、总结
| 连接类型 | 适用场景 | 特点说明 |
|---|---|---|
| INNER JOIN | 需要严格匹配的数据 | 结果集最小,性能最好 |
| LEFT JOIN | 保留左表全部数据 | 常用于主表查询 |
| RIGHT JOIN | 保留右表全部数据 | 可用LEFT JOIN替代 |
| FULL JOIN | 需要两表所有数据 | MySQL需用UNION模拟 |
| CROSS JOIN | 生成组合数据 | 谨慎使用,易产生大数据量 |
| SELF JOIN | 层级关系/树形结构查询 | 必须使用别名 |
最佳实践建议:
- 优先使用INNER JOIN,需要保留全部数据时再用外连接
- 多表连接时,按数据量从小到大排列连接顺序
- 始终为连接的表指定明确的别名
- 复杂查询建议分步调试,先验证单表结果再组合
- 超过3个表连接时,建议使用EXPLAIN分析执行计划
MySQL 子查询全面指南
目录
- 一、子查询类型与使用场景
- 二、不同子查询的SQL示例
- 三、易错点与注意事项
- 四、总结与最佳实践
一、子查询类型与使用场景
1. 标量子查询
特征:返回单个值(一行一列)
场景:在WHERE/SELECT/HAVING等位置作为条件值使用
-- 查询高于平均工资的员工
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees); -- 返回单个数值
2. 列子查询
特征:返回单列多行数据
场景:配合IN/ANY/ALL等运算符使用
-- 查询有订单的客户
SELECT name
FROM customers
WHERE id IN (SELECT DISTINCT customer_id FROM orders -- 返回客户ID列表
);
3. 行子查询
特征:返回单行多列数据
场景:多条件同时比较
-- 查询与张三同部门同职位的员工
SELECT name
FROM employees
WHERE (dept_id, position) = (SELECT dept_id, position FROM employees WHERE name = '张三'
);
4. 表子查询
特征:返回多行多列结果集
场景:作为临时表参与连接查询
-- 查询各部门最高薪员工
SELECT e.dept_id, e.name, e.salary
FROM employees e
INNER JOIN (SELECT dept_id, MAX(salary) AS max_salaryFROM employeesGROUP BY dept_id
) AS tmp
ON e.dept_id = tmp.dept_id AND e.salary = tmp.max_salary;
5. 相关子查询
特征:子查询引用外层查询的字段
场景:逐行处理关联数据
-- 查询工资高于部门平均的员工
SELECT name, salary, dept_id
FROM employees e1
WHERE salary > (SELECT AVG(salary)FROM employees e2WHERE e2.dept_id = e1.dept_id -- 引用外层字段
);
6. EXISTS/NOT EXISTS
特征:检查子查询是否存在结果
场景:存在性验证
-- 查询从未下单的客户
SELECT name
FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
二、不同子查询的SQL示例
1. 在SELECT中使用
-- 显示员工及其部门人数
SELECT name,dept_id,(SELECT COUNT(*) FROM employees e2 WHERE e2.dept_id = e1.dept_id) AS dept_total
FROM employees e1;
2. 在UPDATE中使用
-- 将技术部员工薪资提高10%
UPDATE employees
SET salary = salary * 1.1
WHERE dept_id = (SELECT id FROM departments WHERE dept_name = '技术部'
);
3. 在HAVING中使用
-- 查询订单数超过平均值的客户
SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > (SELECT AVG(order_count) FROM (SELECT COUNT(*) AS order_countFROM ordersGROUP BY customer_id) tmp
);
三、易错点与注意事项
-
性能陷阱
-- 错误:每行执行子查询导致性能低下 SELECT name, (SELECT COUNT(*) FROM orders WHERE customer_id = c.id) AS order_count FROM customers c; -- ✅ 应改用LEFT JOIN优化 -
NULL值问题
-- 当子查询可能返回NULL时 SELECT * FROM products WHERE price > (SELECT MAX(price) FROM discontinued_products); -- 如果子查询结果为NULL,整个WHERE条件会失效 -
多行比较错误
-- 错误:标量子查询返回多行 SELECT name FROM employees WHERE salary = (SELECT salary FROM employees WHERE dept_id = 2 ); -- ✅ 应改用IN或LIMIT 1 -
列不匹配错误
-- 错误:行子查询列数不匹配 SELECT * FROM tableA WHERE (col1, col2) = (SELECT col1 FROM tableB );
四、总结与最佳实践
| 子查询类型 | 适用场景 | 性能建议 |
|---|---|---|
| 标量子查询 | 单值比较 | 优先用于简单条件 |
| EXISTS | 存在性检查 | 比COUNT(*)效率高 |
| 相关子查询 | 逐行依赖外层数据 | 避免在大数据量场景使用 |
| 表子查询 | 复杂数据过滤 | 考虑改用临时表或视图 |
黄金法则:
- 能用连接查询解决的问题,优先使用JOIN(通常性能更好)
- 需要聚合结果作为条件时,子查询更合适
- 对于大数据表,避免在WHERE子句中使用相关子查询
- 始终检查子查询可能返回的NULL值和空结果集
- 必要时使用LIMIT控制子查询返回行数
性能优化提示:
-- 原始慢查询
SELECT * FROM products
WHERE category_id IN (SELECT category_id FROM popular_categories -- 假设返回大量结果
);-- 优化方案:改用JOIN
SELECT p.*
FROM products p
INNER JOIN popular_categories pc
ON p.category_id = pc.category_id;
相关文章:
Mysql基础-多表查询(详细版)
目录 一、表的关系类型与适用场景二、连接方式与使用场景三、易错点与注意事项四、总结 一、表的关系类型与适用场景 1. 一对一关系 场景:一个表的记录对应另一个表的唯一记录 案例:用户表 用户详情表 CREATE TABLE users (id INT PRIMARY KEY,name…...
港科大提出开放全曲音乐生成基础模型YuE:可将歌词转换成完整歌曲
YuE是港科大提出的一个开源的音乐生成基础模型,专为音乐生成而设计,专门用于将歌词转换成完整的歌曲(lyrics2song)。它可以生成一首完整的歌曲,时长几分钟,包括朗朗上口的声乐曲目和伴奏曲目。YuE 能够模拟…...
Python学习第十七天之PyTorch保姆级安装
PyTorch安装与部署 一、准备工作二、pytorch介绍三、CPU版本pytorch安装1. 创建虚拟环境2. 删除虚拟环境1. 通过环境名称删除2. 通过环境路径删除 3. 配置镜像源4. 安装pytorch1. 首先激活环境变量2. 进入pytorch官网,找到安装指令 5. 验证pytorch是否安装成功 四、…...
有关与 WSL 2 的主要区别的信息,请访问 https://aka.ms/wsl2
https://learn.microsoft.com/zh-cn/windows/wsl/install-manual#step-4—download-the-linux-kernel-update-package...
什么是 Java 中的线程安全?
回答 Java 中的线程安全(Thread Safety)指的是在多线程环境下,当多个线程同时访问和操作共享资源(如对象、变量、数据结构等)时,能够保证程序的正确性,不会出现数据不一致、竞争条件࿰…...
计算机视觉(opencv-python)入门之图像的读取,显示,与保存
在计算机视觉领域,Python的cv2库是一个不可或缺的工具,它提供了丰富的图像处理功能。作为OpenCV的Python接口,cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV CV2常用图像处理方…...
QT:Graphics View的坐标系介绍
在 Qt 的 Graphics View 框架中,存在三种不同的坐标系,分别是 物品坐标系(Item Coordinates)、场景坐标系(Scene Coordinates) 和 视图坐标系(View Coordinates)。这三种坐标系在图形…...
530 Login fail. A secure connection is requiered(such as ssl)-java发送QQ邮箱(简单配置)
由于cs的csdN许多文章关于这方面的都是vip文章,而本文是免费的,希望广大网友觉得有帮助的可以多点赞和关注! QQ邮箱授权码到这里去开启 授权码是16位的字母,填入下面的mail.setting里面的pass里面 # 邮件服务器的SMTP地址 host…...
vs2015下使用openmp
一 OPENMP 简介 OpenMP(Open Multi-Processing)是一个基于共享内存的并行编程API,通过编译器指令实现多线程并行开发。其核心特性包括: 1)通过简单的#pragma指令实现并行化 2)支持增量并行(逐步优化代码) 3)跨平台(Windows/Linux/macOS) 4)支持C/C++/Fortra …...
Docker 搭建 Gitlab 服务器 (完整详细版)
参考 Docker 搭建 Gitlab 服务器 (完整详细版)_docker gitlab-CSDN博客 Docker 安装 (完整详细版)_docker安装-CSDN博客 Docker 日常命令大全(完整详细版)_docker命令-CSDN博客 1、Gitlab镜像 # 查找Gitlab镜像 docker search gitlab # 拉取Gitlab镜像 docker pull gitlab/g…...
【万字长文】开源之播对话白鲸开源CEO郭炜--乐观主义的开源精神走得更远
本文为白鲸开源科技CEO郭炜1小时深度访谈全记录 来源于:开源之播」Episode15:对话郭炜–乐观主义的开源精神走得更远 大家好,我是郭炜,开源圈的“郭大侠”。作为 Apache 基金会的成员,我曾参与并孵化了多个开源项目,如…...
机试刷题_674. 最长连续递增序列【python】
674. 最长连续递增序列 class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:if not nums:return 0if len(nums)1:return 1left 0right len(nums)-1tmp []tmp.append(nums[0])res 0while left<right:if nums[left]<nums[left1]:tmp.append(nums[l…...
ipe网络安全
🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 什么是IDS? IDS是英文"Intrusion Detection Systems"的缩写,中文意思是"入侵检测系统"。 大家还记得「网络安全」安…...
QT:QPen、QBrush、与图形抗锯齿的关联
QPen QPen 是 Qt 框架中用于定义绘图时使用的画笔属性的类。在使用 QPainter 进行 2D 绘图时,QPen 可以控制线条的外观,比如线条的颜色、宽度、样式(如实线、虚线等)、端点样式(如方形端点、圆形端点等)和…...
android keystore源码分析
架构 Android Keystore API 和底层 Keymaster HAL 提供了一套基本的但足以满足需求的加密基元,以便使用访问受控且由硬件支持的密钥实现相关协议。 Keymaster HAL 是由原始设备制造商 (OEM) 提供的动态加载库,密钥库服务使用它来提供由硬件支持的加密服…...
【12】智能合约开发入门
12-1 在线合约开发 Cloud IDE简介 基本框架 Cloud IDE是BaaS合约平台提供的在线合约开发工具 IDE是一个去中心化应用(Dapp),通过JavaScript SDK直接与区块链平台通信,进行合约部署和调用 核心功能 合约工程管理 合约编辑与编…...
web安全——分析应用程序
文章目录 一、确定用户输入入口点二、确定服务端技术三、解析受攻击面 一、确定用户输入入口点 在检查枚举应用程序功能时生成的HTTP请求的过程中,用户输入入口点包括: URL文件路径 通常,在查询字符?之前的URL部分并不视为用户输入入口&am…...
Wpf 之Generic.xaml
在 WPF 中,Generic.xaml 是一个特殊的资源文件,它会被自动加载,不需要显式添加。这是 WPF 的命名约定。当 WPF 初始化自定义控件时,它会专门查找这个名字的文件。 这个名字是硬编码在 WPF 框架中的,不能改变。 Generi…...
VidSketch:具有扩散控制的手绘草图驱动视频生成
浙大提出的VidSketch是第一个能够仅通过任意数量的手绘草图和简单的文本提示来生成高质量视频动画的应用程序。该方法训练是在单个 RTX4090 GPU 上进行的,针对每个动作类别使用一个小型、高质量的数据集。VidSketch方法使所有用户都能使用简洁的文本提示和直观的手绘…...
解锁C# XML编程:从新手到实战高手的蜕变之路
一、引言:XML 在 C# 中的关键地位 在 C# 开发的广袤领域中,XML(可扩展标记语言,eXtensible Markup Language)宛如一颗璀璨的明星,占据着举足轻重的地位。它以其独特的结构化和自描述特性,成为了…...
SITS2026幻觉治理黄金三角模型:可信数据源锚定+推理链断点监控+结果置信度动态熔断(行业首曝)
第一章:SITS2026幻觉治理黄金三角模型:可信数据源锚定推理链断点监控结果置信度动态熔断(行业首曝) 2026奇点智能技术大会(https://ml-summit.org) SITS2026首次提出“幻觉治理黄金三角模型”,将大语言模型输出可靠性…...
程序内存分区
文章目录栈区(Stack)堆区(Heap)全局 / 静态区(Global/Static)常量区(Constant)代码区(Code / Text)总结程序运行时,操作系统会将进程的内存空间划…...
Phi-3-mini-4k-instruct-gguf赋能课程设计:自动生成Multisim电路仿真报告
Phi-3-mini-4k-instruct-gguf赋能课程设计:自动生成Multisim电路仿真报告 1. 电子工程学生的文档困境 每次课程设计最头疼的是什么?不是画电路图,不是调参数,而是写那份永远写不完的实验报告。电子工程专业的学生都深有体会&…...
Pixel Dream Workshop 软件测试实战:AI图像生成模型的自动化测试策略
Pixel Dream Workshop 软件测试实战:AI图像生成模型的自动化测试策略 1. 引言:当AI绘画遇上软件测试 最近在测试团队接手了一个有趣的项目——为Pixel Dream Workshop这款AI图像生成工具设计自动化测试方案。说实话,第一次看到那些由AI生成…...
终极Undotree性能优化指南:让Vim撤销历史管理如丝般顺滑
终极Undotree性能优化指南:让Vim撤销历史管理如丝般顺滑 【免费下载链接】undotree The undo history visualizer for VIM 项目地址: https://gitcode.com/gh_mirrors/un/undotree Undotree是Vim编辑器中一款强大的撤销历史可视化插件,它能将复杂…...
别再只调参了!用Python给CFD/CAE仿真结果加个‘AI修正器’,精度提升看得见
用Python构建CFD/CAE仿真AI修正器的工程实践指南 在工程仿真领域,我们常常遇到一个令人头疼的问题:经过精心设置的CFD/CAE仿真结果,与实验数据之间总存在一条难以跨越的"误差鸿沟"。传统解决方案往往是反复调整网格、修改参数或更换…...
详细解析Spring如何解决循环依赖问题蔚
AI训练存储选型的演进路线 第一阶段:单机直连时代 早期的深度学习数据集较小,模型训练通常在单台服务器或单张GPU卡上完成。此时直接将数据存储在训练机器的本地NVMe SSD/HDD上。 其优势在于IO延迟最低,吞吐量极高,也就是“数据离…...
传奇开服必看!MonGen.txt脚本这样写能省30%服务器资源
传奇开服性能优化:MonGen.txt脚本高效编写实战指南 在传奇私服架设过程中,服务器资源占用过高是许多GM面临的共同挑战。特别是当玩家数量增加时,M2引擎的CPU和内存使用率飙升,导致游戏卡顿甚至崩溃。本文将深入解析MonGen.txt脚本…...
图解强化学习 |强化学习在自动加药系统上的尝试(在线更新,和模型微调)
🌞欢迎来到图解强化学习的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 📆首发时间:🌹2026年4月12日🌹 ✉️希望可以和大家一起完成…...
AI 时代的程序员:从“建造者”到“定义者”宋
一、前言:什么是 OFA VQA 模型? OFA(One For All)是字节跳动提出的多模态预训练模型,支持视觉问答、图像描述、图像编辑等多种任务,其中视觉问答(VQA)是最常用的功能之一——输入一张…...
