第二篇,永远写不会的SQL 子查询(Subquery)

一句话!

子查询 = 在一个 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'

);