SQL 多表查询场景速查:一对一、一对多、多对多
在实际开发中,单表查询往往无法满足业务需求,我们需要进行多表查询。多表关系大致分为 一对一、一对多、多对多 三种。本文将带你速查这些场景及其典型 SQL 写法。
一、一对一关系查询
一对一关系通常出现在两张表一一对应的场景,比如用户表和用户详情表。
典型写法:
SELECT u.id, u.name, d.address, d.phone
FROM User u
INNER JOIN UserDetail d ON u.id = d.user_id;
要点:
一对一关系的 JOIN 与一对多类似,但通常主键和外键是唯一绑定。
在设计上有时会拆分表来避免冗余。
二、一对多关系查询
一对多是最常见的关系,比如 一个用户可以有多条订单。
典型写法:
SELECT u.name, o.order_id, o.amount
FROM User u
INNER JOIN Orders o ON u.id = o.user_id;
要点:
一对多查询时,结果集中会重复出现“一”的部分(如用户信息)。
通常需要结合 GROUP BY 或聚合函数做统计,比如用户订单总额:
SELECT u.name, SUM(o.amount) AS total_amount
FROM User u
INNER JOIN Orders o ON u.id = o.user_id
GROUP BY u.id, u.name;
三、多对多关系查询
多对多关系需要 中间表 作为桥梁。比如学生和课程:一个学生可以选多门课程,一门课程也可以被多个学生选。
典型设计:
● Student 学生表
● Course 课程表
● StudentCourse 学生-课程关系表
典型写法:
SELECT s.name, c.course_name
FROM Student s
INNER JOIN StudentCourse sc ON s.id = sc.student_id
INNER JOIN Course c ON sc.course_id = c.id;
要点:
中间表至少包含两列外键(指向两边表)。
查询时通常需要双 JOIN。
四、JOIN 类型选择
● INNER JOIN:只保留两边匹配的数据。
● LEFT JOIN:保留左表所有数据,即使右表无匹配。
● RIGHT JOIN:保留右表所有数据,即使左表无匹配。
示例:
-- 查询所有用户,即使没有订单
SELECT u.name, o.order_id
FROM User u
LEFT JOIN Orders o ON u.id = o.user_id;
五、面试高频问题
1. 一对一关系如何查询?
使用唯一外键连接,结果唯一对应。
2. 一对多查询结果会出现什么问题?
会出现重复记录,通常需要用聚合函数或 GROUP BY 处理。
3. 多对多如何建模?
需要引入中间表,避免直接的多对多关系。
六、总结
一对一:两表一一对应,常见于扩展表。
一对多:主表信息会重复,需要聚合处理。
多对多:必须通过中间表实现,再用双 JOIN 查询。
一句话记忆:“一对一靠唯一键,一对多靠外键,多对多靠中间表。”