一句话!
子查询 = 在一个 SQL 语句里面,再写一个 SQL 语句
但其实看到题就麻爪,无语
想象你在做一件事,你想找:成绩高于"全班平均分"的学生。问题来了,你不知道平均分是多少,但你知道怎么算平均分。那可以先算平均分,然后再用这个结果去筛学生。这句话翻成 SQL,就是子查询
SQL 写法:
SELECT *
FROM students
WHERE score > (
SELECT AVG(score)
FROM students
);
子查询一定先执行
数据库看到这条 SQL 时:WHERE score > ( SELECT AVG(score) FROM students )
它的想法是:等等,我现在不知道这个值是多少,我先去执行括号里的那条 SQL。
所以顺序永远是:执行子查询,拿结果,再执行外面的查询。
子查询不仅可以返回一个值,也可以返回一堆值
比如:
SELECT *
FROM students
WHERE major IN (
SELECT major
FROM departments
);
这里要用in,WHERE major IN (子查询) = major 属不属于子查询算出来的那一堆值,NOT IN 也一样(反过来筛)
EXISTS = 子查询"有没有返回至少一行"。它不关心值是什么,只关心有没有结果。
example:找出有选过课的学生
SELECT *
FROM students s
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE e.student_id = s.student_id
);
子查询的意思是:在 enrollments 里,有没有一条记录的 student_id = 当前这个学生?
EXISTS 的判断规则:找到 第一行 → EXISTS = TRUE;一行都找不到 → EXISTS = FALSE
SELECT 1 是因为:值不重要,只要有行就行
数据库是这样想的:"我拿一个学生 → 去 enrollments 里看一眼只要看到一条匹配的记录,我就停。" 不会把所有结果都算完
EXISTS 不比较值,所以不怕 NULL。
SQL229 使用子查询的方式找出属于Action分类的所有电影对应的title,description
select
f.title,
f.description
from
film f
join film_category fc on f.film_id = fc.film_id
where
category_id in (
select
c.category_id
from
category c
join film_category f on c.category_id = f.category_id
where
c.name = 'Action'
);