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)宛如一颗璀璨的明星,占据着举足轻重的地位。它以其独特的结构化和自描述特性,成为了…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...
【大厂机试题解法笔记】矩阵匹配
题目 从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150 输入格式 N M K N*M矩阵 输…...
前端打包工具简单介绍
前端打包工具简单介绍 一、Webpack 架构与插件机制 1. Webpack 架构核心组成 Entry(入口) 指定应用的起点文件,比如 src/index.js。 Module(模块) Webpack 把项目当作模块图,模块可以是 JS、CSS、图片等…...
分布式计算框架学习笔记
一、🌐 为什么需要分布式计算框架? 资源受限:单台机器 CPU/GPU 内存有限。 任务复杂:模型训练、数据处理、仿真并发等任务耗时严重。 并行优化:通过任务拆分和并行执行提升效率。 可扩展部署:适配从本地…...
【靶场】XXE-Lab xxe漏洞
前言 学习xxe漏洞,搭了个XXE-Lab的靶场 一、搭建靶场 现在需要登录,不知道用户名密码,先随便试试抓包 二、判断是否存在xxe漏洞 1.首先登录抓包 看到xml数据解析,由此判断和xxe漏洞有关,但还不确定xxe漏洞是否存在。 2.尝试xxe 漏洞 判断是否存在xxe漏洞 A.send to …...
