深入解析多表联查(MySQL)

news2025/4/22 8:04:34

前言

在面试中以及实际开发中,多表联查是每个程序员必备技能,下文通过最简单的学生表和课程表的实例帮大家最快入门多表联查技能。

建立数据表

1. 学生表(students)

创建学生表

CREATE TABLE students (
    student_id INT AUTO_INCREMENT PRIMARY KEY,
    student_name VARCHAR(50) NOT NULL,
    gender ENUM('男','女') DEFAULT NULL,
    age TINYINT UNSIGNED
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入学生数据(20条)

INSERT INTO students (student_name, gender, age) VALUES
('李明', '男', 18), ('王芳', '女', 19), ('张伟', '男', 20),
('赵敏', '女', 18), ('陈强', '男', 19), ('周雪', '女', 20),
('黄磊', '男', 21), ('吴倩', '女', 19), ('徐洋', '男', 18),
('孙莉', '女', 20), ('马超', '男', 19), ('朱婷', '女', 21),
('何军', '男', 18), ('林琳', '女', 20), ('郑凯', '男', 19),
('胡月', '女', 21), ('郭涛', '男', 18), ('高菲', '女', 20),
('曹阳', '男', 19), ('丁薇', '女', 18);

得到以下结果
在这里插入图片描述

2. 课程表 (courses)

创建课程表

CREATE TABLE courses (
    course_id INT AUTO_INCREMENT PRIMARY KEY,
    course_name VARCHAR(50) NOT NULL,
    credit TINYINT UNSIGNED
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入课程数据(20条)

INSERT INTO courses (course_name, credit) VALUES
('高等数学', 4), ('大学英语', 3), ('计算机基础', 2),
('数据结构', 4), ('操作系统', 3), ('数据库原理', 4),
('计算机网络', 3), ('软件工程', 2), ('人工智能', 4),
('数字电路', 3), ('编译原理', 4), ('算法设计', 3),
('图形学', 2), ('机器学习', 4), ('网络安全', 3),
('移动开发', 2), ('大数据分析', 4), ('物联网技术', 3),
('嵌入式系统', 2), ('计算机组成', 4);

得到以下结果
在这里插入图片描述

3. 选课关系表 (student_courses)

创建选课关系表

CREATE TABLE student_courses (
    student_id INT NOT NULL,
    course_id INT NOT NULL,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES students(student_id) ON DELETE CASCADE,
    FOREIGN KEY (course_id) REFERENCES courses(course_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入选课关系

INSERT INTO student_courses (student_id, course_id) VALUES
(1,1), (1,3), (1,15),
(2,2), (2,14), (2,6),
(3,5), (3,17), (4,11), 
(4,13), (5,5), (7,2), 
(9,4), (9,16), (11,5), 
(13,17), (15,1), (16,13), 
(17,5), (18,12), (19,14), 
(19,16), (19,15), (19,17),          
(20,17), (20,19);

得到以下结果
在这里插入图片描述

多表联查理论及实现

1. 查询学生选课详情

以上需求可以使用隐式的内连接(INNER JOIN),只有当 ON 条件匹配时,记录才会被返回。
如果某个学生没有选课,或者某些课程没有学生选修,这些记录不会出现在结果中。
完整代码如下:

SELECT s.student_name, c.course_name 
FROM students s
JOIN student_courses sc ON s.student_id = sc.student_id
JOIN courses c ON sc.course_id = c.course_id;

代码详解:

SELECT s.student_name, c.course_name

这部分指定了查询结果中需要显示的字段:

  • s.student_name:从 students 表中获取的学生姓名。
  • c.course_name::从 courses 表中获取的课程名称。

别名 s 和 c 分别代表 students 表和 courses 表。

FROM students s

查询的起点是 students 表,并给它指定了一个别名 s,以便在后续代码中简化引用。

JOIN student_courses sc ON s.student_id = sc.student_id

使用 JOIN 将 students 表与 student_courses 表连接起来。
连接条件是 s.student_id = sc.student_id,即学生的 ID 在两个表中必须匹配。
这一步是为了找到每个学生选了哪些课程(通过中间表 student_courses)。

JOIN courses c ON sc.course_id = c.course_id

再次使用 JOIN 将 student_courses 表与 courses 表连接起来。
连接条件是 sc.course_id = c.course_id,即课程的 ID 在两个表中必须匹配。
这一步是为了获取每个课程的具体信息(例如课程名称)。
查询结果
在这里插入图片描述

2. 统计课程选修人数

以上需求可以使用 INNER JOIN,结果会返回有学生选修的课程,而未被选修的课程不会出现在结果中。
使用 LEFT JOIN 可以确保所有课程都出现在结果中,即使它们没有被选修。

SELECT c.course_name, COUNT(sc.student_id) AS student_count 
FROM courses c
LEFT JOIN student_courses sc ON c.course_id = sc.course_id
GROUP BY c.course_id;

代码详解:

SELECT c.course_name, COUNT(sc.student_id) AS student_count

这部分指定了查询结果中需要显示的字段:

  • c.course_name::从 courses 表中获取的课程名称。
  • COUNT(sc.student_id):统计每个课程的学生数量。
  • sc.student_id 是 student_courses 表中的字段,表示选修该课程的学生 ID。

如果某课程没有任何学生选修,则 sc.student_id 的值为 NULL,COUNT 函数会忽略 NULL 值,因此返回的结果是 0。
别名 student_count 用于给统计结果命名。

FROM courses c

查询的起点是 courses 表,并给它指定了一个别名 c,以便在后续代码中简化引用。

LEFT JOIN student_courses sc ON c.course_id = sc.course_id

使用 LEFT JOIN 将 courses 表与 student_courses 表连接起来。
连接条件是 c.course_id = sc.course_id,即课程的 ID 在两个表中必须匹配。
LEFT JOIN 的特点:
它会保留左表(courses 表)的所有记录,即使右表(student_courses 表)中没有匹配的记录。
如果某课程没有任何学生选修,sc.student_id 的值将为 NULL,但该课程仍会出现在结果中。

GROUP BY c.course_id

按照 c.course_id 对结果进行分组。
每个课程对应一组数据,COUNT(sc.student_id) 会统计每个课程的学生数量。
查询结果
在这里插入图片描述

3. 查询未选课学生

SELECT s.* 
FROM students s
LEFT JOIN student_courses sc ON s.student_id = sc.student_id 
WHERE sc.course_id IS NULL;

代码详解

SELECT s.*

这部分指定了查询结果中需要显示的字段。
使用 s.* 表示从 students 表中获取所有字段(即所有学生信息)。
别名 s 是 students 表的简写。

FROM students s

查询的起点是 students 表,并给它指定了一个别名 s,以便在后续代码中简化引用。

LEFT JOIN student_courses sc ON s.student_id = sc.student_id

使用 LEFT JOIN 将 students 表与 student_courses 表连接起来。
连接条件是 s.student_id = sc.student_id,即学生的 ID 在两个表中必须匹配。
LEFT JOIN 的特点:
它会保留左表(students 表)的所有记录,即使右表(student_courses 表)中没有匹配的记录。
如果某学生没有选修任何课程,则 sc.course_id 的值将为 NULL。

WHERE sc.course_id IS NULL

过滤条件是 sc.course_id IS NULL,即只选择那些在 student_courses 表中没有匹配记录的学生。
换句话说,这部分筛选出的是没有选修任何课程的学生
查询结果
在这里插入图片描述

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

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

相关文章

宇视设备视频平台EasyCVR打造智慧酒店安防体系,筑牢安全防线

一、需求背景 酒店作为人员流动频繁的场所,对安全保障与隐私保护有着极高的要求。为切实维护酒店内部公共区域的安全秩序,24小时不间断视频监控成为必要举措。通常情况下,酒店需在本地部署视频监控系统以供查看,部分连锁酒店还希…

Linux中的文件传输(附加详细实验案例)

一、实验环境的设置 ①该实验需要两台主机,虚拟机名称为 L2 和 L3 ,在终端分别更改主机名为 node1 和 node2,在实验过程能够更好分辨。 然后再重新打开终端,主机名便都更改了相应的名称。 ②用 ip a 的命令分别查看两个主机的 …

基于 OpenHarmony 5.0 的星闪轻量型设备应用开发——Ch2 OpenHarmony LiteOS-M 内核应用开发

写在前面: 此篇是系列文章《基于 OpenHarmony5.0 的星闪轻量型设备应用开发》的第 2 章。本篇介绍了如何在 OpenHarmony 5.0 框架下,针对 WS63 进行 LiteOS-M 内核应用工程的开发。 为了方便读者学习,需要OpenHarmony 5.0 WS63 SDK 的小伙伴可…

Linux--线程概念与控制

目录 1. Linux线程概念 1-1 什么是线程 1-2 分⻚式存储管理 1-2-1 虚拟地址和⻚表的由来 1-2-2 物理内存管理 1-2-3 ⻚表 1-2-4 ⻚⽬录结构 1-2-5 两级⻚表的地址转换 1-2-6 缺⻚异常 1-3 线程的优点 1-4 线程的缺点 1-5 线程异常 1-6 线程⽤途 2. Linux进程VS线…

Python | kelvin波的水平空间结构

写在前面 简单记录一下之前想画的一个图: 思路 整体比较简单,两个子图,本质上就是一个带有投影,一个不带投影,通常用在EOF的空间模态和时间序列的绘制中,可以看看之前的几个详细的画法。 Python | El Ni…

【音视频】SDL播放PCM音频

相关API 打开音频设备 int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained); desired:期望的参数。obtained:实际音频设备的参数,一般情况下设置为NULL即可。 SDL_AudioSpec typedef struct SDL_AudioSpec { i…

BERT - Bert模型框架复现

本节将实现一个基于Transformer架构的BERT模型。 1. MultiHeadAttention 类 这个类实现了多头自注意力机制(Multi-Head Self-Attention),是Transformer架构的核心部分。 在前几篇文章中均有讲解,直接上代码 class MultiHeadAtt…

docker创建容器添加启动--restart选项

一、通过 Docker 命令直接修改已启动的容器&#xff08;推荐-已验证&#xff09; 操作步骤&#xff1a; 1.执行更新命令&#xff1a; docker update --restartalways <容器名或ID>此命令会将容器的重启策略调整为 always&#xff08;无论容器以何种状态退出&#xff0…

一文读懂WPF系列之常用控件以及样式

WPF控件 控件分类概览常用控件常用控件代码示例和效果 样式与模板应用样式定义​​方式行内样式​​页面/窗口级资源样式&#xff08;Local Resource&#xff09;应用程序全局资源独立资源字典&#xff08;ResourceDictionary&#xff09;控件模板&#xff08;ControlTemplate&…

【双指针】专题:LeetCode 283题解——移动零

移动零 一、题目链接二、题目三、题目解析四、算法原理两个指针的作用以及三个区间总结 五、与快速排序的联系六、编写代码七、时间复杂度、空间复杂度 一、题目链接 移动零 二、题目 三、题目解析 “保持非零元素的相对顺序”&#xff0c;比如&#xff0c;示例1中非零元素1…

2025蓝桥杯JavaB组

说明 博主自己水平有限&#xff0c;而且答案也不一定对&#xff0c;下面代码和思路仅作分享。我只把我考场上做了的写出来了&#xff0c;有什么问题欢迎评论区交流。 A&#xff1a;逃离高塔 思路&#xff1a; 由于有了去年的经验&#xff0c;所以一上来我就是找规律&#xf…

SQL学习--基础语法学习

SQL和excle对比 学习目标 单表查询 项目背景 SQL 练习环境 SQL Online Compiler - Next gen SQL Editor 商品信息表&#xff1a;https://study-zhibo.oss-cn-shanghai.aliyuncs.com/test/%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E8%A1%A8.csv 订单明细表&#xff1a;https://…

MATLAB2022b安装

1 从百度网盘下载MATLAB2022b&#xff0c;下载完成后解压到某个文件夹&#xff1b; 链接: MATLAB2022b 提取码: 6666 2 打开解压后的文件夹&#xff0c;进入setup文件夹&#xff0c;双击打开“setup.exe”文件&#xff1b; 3 在弹出窗口中选择“高级选项”-->“我有文件安…

架构总览怎么写,才算工业级?

📈系统架构文档是整个项目最重要的起点,但很多人第一章就“写穿了”: 不是写得太细,就是没有重点。想要写出高质量、能协作、能传承的架构文档,这一篇会告诉你应该怎么做—— ✅ 架构总览的终极目标 明确边界、定义角色、画清数据流 别讲执行细节,别深入函数调用。 ✅ 架…

Datawhale 入驻 GitCode:以开源力量推动 AI 教育公平与创新

在 AI 技术深度重塑教育生态的今天&#xff0c;国内首个 AI 开源学习社区 —— Datawhale 正式加入 GitCode 开源平台&#xff01;作为覆盖全球 3000 高校、培养超百万 AI 人才的创新社区&#xff0c;Datawhale 将通过开源协作模式&#xff0c;为人工智能教育公平注入新动能&a…

ChatDBA:一个基于AI的智能数据库助手

今天给大家介绍一个基于 AI 大语言模型实现数据库故障诊断的智能助手&#xff1a;ChatDBA。 ChatDBA 是由上海爱可生信息技术股份有限公司开发&#xff0c;通过对话交互&#xff0c;提供数据库故障诊断、专业知识学习、SQL 生成和优化等功能&#xff0c;旨在提升 DBA 工作效率。…

MacOS中的鼠标、触控板的设置研究

一、背景和写这篇文章的原因 想搞清楚和配置好鼠标&#xff0c;比如解决好为什么我的滚动那么难用&#xff1f;怎么设置滚轮的方向跟windows相同&#xff1f;调整双击速度&#xff0c;调整鼠标滚轮左右拨动的"冷却时间"。 二、各种设置之详细解释 1. MacOS设置 -&…

asp.net core 项目发布到 IIS 服务器

目录 一、VS2022 发布 二、设置IIS服务 三、配置IIS管理器 &#xff08;一&#xff09;打开IIS管理器 &#xff08;二&#xff09;添加站台 &#xff08;三&#xff09;配置应用程式集区 四、安装ASP.NET Core Hosting Bundle 五、设定IIS的日志位置 六、测试 一、VS2…

【Nodebb系列】Nodebb笔记写入方案

NodeBB写入方案 前言 最近在整理以前记录的碎片笔记&#xff0c;想把它们汇总到NodeBB中&#xff0c;方便管理和浏览。但是笔记内容有点多&#xff0c;并且用发帖的形式写到NodeBB中会丢失时间信息&#xff0c;因此整理了一套NodeBB写入方案&#xff0c;大致流程如下&#xf…

计算机视觉——基于YOLOV8 的人体姿态估计训练与推理

概述 自 Ultralytics 发布 YOLOV5 之后&#xff0c;YOLO 的应用方向和使用方式变得更加多样化且简单易用。从图像分类、目标检测、图像分割、目标跟踪到关键点检测&#xff0c;YOLO 几乎涵盖了计算机视觉的各个领域&#xff0c;似乎已经成为计算机视觉领域的“万能工具”。 Y…