子查询基本概念

子查询是指嵌套在 SELECT、INSERT、UPDATE 或 DELETE 语句中的查询语句,必须放在圆括号内。子查询可以多层嵌套。

 

子查询执行顺序

 先执行最内层的子查询

 将子查询结果传递给外层查询

 最后执行外层查询

 

WHERE 子句中的子查询

1. IN/NOT IN 子查询

用于判断表达式是否在子查询结果集中。

示例1:查询选修了特定课程的学生

SELECT name FROM students 
WHERE course_id IN (SELECT id FROM courses WHERE course_name IN ('Java', 'Python'));

示例2:查询没有选修任何课程的学生

SELECT name FROM students
WHERE id NOT IN (SELECT student_id FROM student_courses);

2. 比较运算符子查询

使用 =, <>, >, <, >=, <= 等比较运算符。

 

示例3:查询成绩高于平均成绩的学生

SELECT student_name FROM scores
WHERE score > (SELECT AVG(score) FROM scores);

3. EXISTS/NOT EXISTS 子查询

检查子查询是否返回结果,不关心具体内容。

 

示例4:查询有选修课程的学生

SELECT name FROM students s
WHERE EXISTS (SELECT 1 FROM student_courses sc WHERE sc.student_id = s.id);

示例5:查询没有选修任何课程的学生

SELECT name FROM students s
WHERE NOT EXISTS (SELECT 1 FROM student_courses sc WHERE sc.student_id = s.id);

FROM 子句中的子查询(派生表)

子查询可以作为临时表使用。

 

示例6:查询每门课程的平均成绩

SELECT c.course_name, avg_scores.avg_score
FROM courses c
JOIN (SELECT course_id, AVG(score) as avg_score FROM scores GROUP BY course_id) avg_scores
ON c.id = avg_scores.course_id;

SELECT 子句中的子查询(标量子查询)

 

示例7:查询每个学生的姓名和他们的成绩与平均成绩的差值

SELECT 
    student_name,
    score,
    score - (SELECT AVG(score) FROM scores) as diff_from_avg
FROM scores;

多列子查询

示例8:查询与特定学生年龄和性别相同的学生

SELECT name FROM students
WHERE (age, gender) = (SELECT age, gender FROM students WHERE name = '张三');

相关子查询

子查询引用外层查询的列。

 

示例9:查询成绩高于该课程平均成绩的学生

SELECT s.student_name, c.course_name, sc.score
FROM scores sc
JOIN students s ON sc.student_id = s.id
JOIN courses c ON sc.course_id = c.id
WHERE sc.score > (
    SELECT AVG(score) 
    FROM scores 
    WHERE course_id = sc.course_id
);

子查询性能优化建议

1. 对于 IN 子查询,当数据量大时考虑改用 JOIN

2. EXISTS 通常比 IN 性能更好,特别是子查询结果集大时

3. 避免在子查询中使用 SELECT *,只选择需要的列

4. 为子查询中的连接条件建立索引

 

子查询与连接的选择

 当需要从多个表获取数据但只关心一个表的记录时,使用子查询

 当需要从多个表获取数据并组合显示时,使用连接

 子查询通常更易读,但连接有时性能更好

点赞(2)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)