SQL 连接查询用法总结

SQL 连接查询用法总结

核心:多表通过关联字段拼接数据,分为内连接、左连接、右连接、全连接、交叉连接

一、基础语法通用格式

sql 复制代码
SELECT 字段
FROM 表1
连接类型 JOIN 表2
ON 表1.关联字段 = 表2.关联字段;

二、五类连接详解

1. 内连接 INNER JOIN

只返回两表匹配成功的数据,交集部分

sql 复制代码
SELECT *
FROM user u
INNER JOIN order o
ON u.id = o.user_id;

简写:可省略INNER,直接写JOIN

2. 左连接 LEFT JOIN

左表为基准,左表数据全部保留,右表匹配不上显示null

sql 复制代码
-- 查询所有用户及对应订单,无订单也保留用户
SELECT *
FROM user u
LEFT JOIN order o
ON u.id = o.user_id;

3. 右连接 RIGHT JOIN

右表为基准,右表数据全部保留,左表匹配不上显示null

sql 复制代码
SELECT *
FROM user u
RIGHT JOIN order o
ON u.id = o.user_id;

4. 全连接 FULL JOIN

取两表所有数据,匹配不上字段补空

sql 复制代码
SELECT *
FROM user u
FULL JOIN order o
ON u.id = o.user_id;

注:MySQL不原生支持,可用左右连接合并实现

5. 交叉连接 CROSS JOIN

笛卡尔积,两表行数相乘组合,极少主动使用

sql 复制代码
SELECT * FROM user CROSS JOIN goods;

三、关键区分速记

连接类型 数据范围 使用场景
INNER JOIN 两边匹配数据 只查有关联的有效数据
LEFT JOIN 左表全部+匹配右表 主表数据必展示,附属信息可选
RIGHT JOIN 右表全部+匹配左表 极少用,可互换表改用左连接
FULL JOIN 两表全部数据 汇总全部台账数据

四、常用拓展写法

  1. 多表连续连接
sql 复制代码
SELECT *
FROM user u
LEFT JOIN order o ON u.id=o.user_id
LEFT JOIN pay p ON o.id=p.order_id;
  1. 连接后加筛选条件
  • ON:连接前过滤关联规则
  • WHERE:连接结果后整体筛选
sql 复制代码
SELECT *
FROM user u
LEFT JOIN order o ON u.id=o.user_id
WHERE o.create_time>'2025-01-01';

五、实操要点

  1. 关联字段一般为主键、外键,保证对应关系
  2. 字段重名需加表别名区分
  3. 优先左连接,可读性更高,日常业务最常用
  4. 内连接自动过滤无效无关联数据

六、例题

学生表: Students

Column Name Type
student_id int
student_name varchar

在 SQL 中,主键为 student_id(学生ID)。

该表内的每一行都记录有学校一名学生的信息。

科目表: Subjects

Column Name Type
subject_name varchar
在 SQL 中,主键为 subject_name(科目名称)。
每一行记录学校的一门科目名称。

考试表: Examinations

Column Name Type
student_id int
subject_name varchar

这个表可能包含重复数据(换句话说,在 SQL 中,这个表没有主键)。

学生表里的一个学生修读科目表里的每一门科目。

这张考试表的每一行记录就表示学生表里的某个学生参加了一次科目表里某门科目的测试。

查询出每个学生参加每一门科目测试的次数,结果按 student_id 和 subject_name 排序。

查询结构格式如下所示。

示例 1:

输入:

Students table:

student_id student_name
1 Alice
2 Bob
13 John
6 Alex

Subjects table:

subject_name
Math
Physics
Programming

Examinations table:

student_id subject_name
1 Math
1 Physics
1 Programming
2 Programming
1 Physics
1 Math
13 Math
13 Programming
13 Physics
2 Math
1 Math

输出:

student_id student_name subject_name attended_exams
1 Alice Math 3
1 Alice Physics 2
1 Alice Programming 1
2 Bob Math 1
2 Bob Physics 0
2 Bob Programming 1
6 Alex Math 0
6 Alex Physics 0
6 Alex Programming 0
13 John Math 1
13 John Physics 1
13 John Programming 1

解释:

结果表需包含所有学生和所有科目(即便测试次数为0):

Alice 参加了 3 次数学测试, 2 次物理测试,以及 1 次编程测试;

Bob 参加了 1 次数学测试, 1 次编程测试,没有参加物理测试;

Alex 啥测试都没参加;

John 参加了数学、物理、编程测试各 1 次。

题目分析 + 左外连接完整解法

这道题是经典的多表左连接 + 分组统计 考题,核心难点在于:
必须让每个学生 × 每门科目都出现一行,哪怕一次考试都没参加


解题思路

  1. 生成「所有学生 × 所有科目」的完整组合
  • 学生表(所有学生)
  • 科目表(所有科目)
  • 笛卡尔积(CROSS JOIN) 生成:每个学生对应每一门科目
    → 这是保证「不漏学生、不漏科目」的关键
  1. 左连接考试表,统计参加次数
  • LEFT JOIN 把考试表关联上去
  • 没参加考试的次数记为 0
  1. 分组 + 排序
  • student_id, subject_name 分组统计次数
  • 最后按要求排序

最终 SQL 代码

sql 复制代码
SELECT
  s.student_id,
  s.student_name,
  sub.subject_name,
  COUNT(e.student_id) AS attended_exams  -- 统计考试次数
FROM
  Students s
CROSS JOIN
  Subjects sub  -- 生成 每个学生 × 每门科目
LEFT JOIN
  Examinations e  -- 左连接考试表(不丢组合)
  ON s.student_id = e.student_id
  AND sub.subject_name = e.subject_name
GROUP BY
  s.student_id, s.student_name, sub.subject_name
ORDER BY
  s.student_id, sub.subject_name;

关键步骤解释

  1. CROSS JOIN 作用
    Students CROSS JOIN Subjects

    直接生成:所有学生 × 所有科目 的完整组合

    哪怕学生没考过某科目,这一行依然存在

  2. LEFT JOIN 为什么必须这么写

sql 复制代码
LEFT JOIN Examinations e
  ON s.student_id = e.student_id
  AND sub.subject_name = e.subject_name
  • 以「学生+科目」为主表
  • 左边完整保留
  • 右边匹配不到考试记录 → 显示 NULL
  • COUNT(e.student_id) 会自动把 NULL 记为 0
  1. 统计次数
    COUNT(e.student_id)
  • 参加过 → 计数 +1
  • 没参加 → 计 0

为什么不能直接用考试表?

因为考试表里缺少没参加考试的学生/科目组合

直接统计会漏数据,必须先生成完整组合,再左连接考试表。

相关推荐
arronKler17 小时前
数据库锁总结
数据库·oracle
努力努力再努力wz17 小时前
【Redis入门系列】:从 hashtable到 listpack:深入理解 Hash 底层编码、字段级过期、核心命令与缓存应用
开发语言·数据结构·数据库·c++·redis·算法·缓存
还是鼠鼠17 小时前
AI掘金头条新闻系统 (Toutiao News)-封装通用成功响应格式
数据库·后端·python·fastapi·web
猎嘤一号17 小时前
Python 打包成 EXE 完整教程(单文件 \+ 整个工程)
数据库·python·microsoft
数据库小学妹17 小时前
分布式数据库架构演进:从集中式到分布式,三大路线一次讲清楚
数据库·分布式·数据库架构
洛水水17 小时前
redis缓存:雪崩、穿透、击穿详解
数据库·redis·缓存
juniperhan17 小时前
Flink 系列第25篇:Flink SQL 集成 Hive 实践:流批一体下的实时数仓利器
大数据·数据仓库·hive·分布式·sql·flink
暴躁小师兄数据学院17 小时前
【AI大数据工程师特训笔记】第01讲:数据库基本概念
大数据·数据库·笔记
杨云龙UP17 小时前
Oracle Flashback Query 实战练习:误更新、误删除数据如何快速找回?
linux·运维·数据库·sql·oracle·flashback