SQL 子查询与多表 JOIN 用法大全(速查版)
在 SQL 学习和面试中,子查询 和 多表 JOIN 是两类非常常见的语法点。很多人对它们的适用场景和区别容易混淆。本文将带你速查这两类用法,并结合典型示例,帮你快速掌握核心要点。
一、什么是子查询?
子查询(Subquery)是指将一个查询嵌套在另一个查询中,常用于条件过滤、结果生成或虚拟表。
常见场景:
1. 条件过滤(常与 WHERE 搭配)
2. 结果生成(嵌套在 SELECT 中)
3. 虚拟表(嵌套在 FROM 中,相当于临时表)
示例:
-- 查询成绩最高的学生
SELECT name, score
FROM Student
WHERE score = (SELECT MAX(score) FROM Student);
这里 (SELECT MAX(score) FROM Student) 就是一个子查询。
二、子查询的分类
1. 标量子查询
返回单个值,可以放在 WHERE 或 SELECT 中。
SELECT name, score
FROM Student
WHERE score > (SELECT AVG(score) FROM Student);
2. 列子查询
返回一列,用 IN、ANY、ALL 等关键字进行比较。
SELECT name
FROM Student
WHERE id IN (SELECT student_id FROM Course WHERE course_name = '数学');
3. 表子查询
返回多列多行,相当于一个虚拟表。
SELECT t.name, t.score
FROM (SELECT name, score FROM Student WHERE score > 90) t;
三、什么是 JOIN?
JOIN 用于把多张表关联起来查询,核心思想是通过某个公共字段(通常是主键和外键)将数据拼接在一起。
常见 JOIN 类型:
1. INNER JOIN:只返回两表匹配的数据。
2. LEFT JOIN:保留左表全部数据,右表不匹配时返回 NULL。
3. RIGHT JOIN:保留右表全部数据,左表不匹配时返回 NULL。
4. FULL JOIN(部分数据库支持):返回两表所有数据,不匹配的部分补 NULL。
示例:
-- 查询每个学生和对应的课程
SELECT s.id, s.name, c.course_name
FROM Student s
INNER JOIN Course c ON s.id = c.student_id;
四、子查询 vs JOIN
在很多场景下,子查询和 JOIN 都能实现相同的结果,但它们的逻辑不同:
子查询:逻辑更直观,适合分步思考,常用于条件过滤。
JOIN:执行效率通常更高,适合一次性拼接数据。
示例对比:
-- 子查询写法:找出选修“数学”的学生
SELECT name
FROM Student
WHERE id IN (
SELECT student_id FROM Course WHERE course_name = '数学'
);
-- JOIN 写法:找出选修“数学”的学生
SELECT s.name
FROM Student s
INNER JOIN Course c ON s.id = c.student_id
WHERE c.course_name = '数学';
两者的结果相同,但执行效率上,JOIN 往往优于子查询。
五、面试高频陷阱
1. 问:子查询一定比 JOIN 慢吗?
不一定,现代数据库优化器会自动将子查询优化成 JOIN,但复杂嵌套子查询依然可能性能差。
2. 问:什么时候用子查询更合适?
当逻辑分步骤清晰,或者 JOIN 写法过于复杂时。
3. 问:什么时候用 JOIN 更合适?
需要大表关联、聚合统计,且结果要高性能时。
六、最佳实践
1. 能用 JOIN 的地方尽量用 JOIN,性能更好。
2. 子查询更适合逻辑清晰的条件过滤,特别是 IN、EXISTS 场景。
3. 大数据场景下,避免过度嵌套子查询,容易拖慢查询效率。
七、总结
子查询:擅长条件过滤,逻辑直观。
JOIN:擅长多表拼接,性能更高。
面试时,能熟练切换子查询和 JOIN 的写法,是 SQL 水平的体现。
一句话记忆:
“子查询重逻辑,JOIN 重效率。”