LeetCode SQL 从入门到精通(MySQL)06(上)

子查询入门,从零理解 Subquery

前面我们已经掌握了各种 JOIN。从本篇开始,我们学习 SQL 中另一项核心能力------子查询(Subquery)。

很多 LeetCode 中等题,都会用到子查询。


一、什么是子查询?

子查询:

一个 SQL 查询嵌套在另一个 SQL 查询里面。

例如:

复制代码
SELECT *
FROM Employee
WHERE salary >
(
    SELECT AVG(salary)
    FROM Employee
);

里面:

复制代码
SELECT AVG(salary)
FROM Employee

就是子查询。

外层 SQL 使用子查询的结果继续筛选。


二、执行顺序

数据库首先执行:

复制代码
SELECT AVG(salary)
FROM Employee;

假设结果:

复制代码
6500

那么整个 SQL 相当于:

复制代码
SELECT *
FROM Employee
WHERE salary > 6500;

所以:

子查询通常先执行,再把结果交给外层查询。


三、返回一个值(标量子查询)

最常见的子查询。

例如:

查询工资最高的人:

复制代码
SELECT *
FROM Employee
WHERE salary=
(
    SELECT MAX(salary)
    FROM Employee
);

里面:

复制代码
MAX(salary)

只返回一个值。

因此:

可以直接比较。


四、返回一列

例如:

复制代码
SELECT *
FROM Orders
WHERE customerId IN
(
    SELECT id
    FROM Customers
    WHERE country='China'
);

子查询:

返回:

复制代码
1
5
8
10

外层:

使用:

复制代码
IN

判断。


五、返回一张表

子查询也可以作为临时表。

例如:

复制代码
SELECT *
FROM
(
    SELECT
        departmentId,
        AVG(salary) avg_salary
    FROM Employee
    GROUP BY departmentId
) t;

这里:

子查询返回:

一张新的结果表。

外层:

把它当普通表继续查询。


六、子查询出现的位置

WHERE

最常见。

复制代码
WHERE salary>
(
    SELECT AVG(salary)
    FROM Employee
)

FROM

作为临时表。

复制代码
FROM
(
    ...
) t

必须起别名。


SELECT

也可以。

例如:

复制代码
SELECT
    name,
    (
        SELECT COUNT(*)
        FROM Orders o
        WHERE o.customerId=c.id
    ) AS order_cnt
FROM Customers c;

不过这种写法效率通常不高。


七、LeetCode 高频题

① 高于平均工资

复制代码
SELECT *
FROM Employee
WHERE salary >
(
    SELECT AVG(salary)
    FROM Employee
);

② 最高工资

复制代码
SELECT *
FROM Employee
WHERE salary=
(
    SELECT MAX(salary)
    FROM Employee
);

③ 某些用户的订单

复制代码
WHERE customerId IN
(
    SELECT ...
)

八、子查询与 JOIN 如何选择?

很多题:

JOIN 和子查询都能完成。

例如:

查询部门平均工资。

可以:

先 GROUP BY。

也可以:

子查询。

原则:

  • 逻辑简单,子查询更容易理解。

  • 多表关联频繁,JOIN 更直观。

  • 实际工作中,两者通常可以互相转换。


九、常见错误

错误一

子查询返回多行,却使用:

复制代码
=

例如:

复制代码
WHERE id=
(
    SELECT id
    FROM ...
)

如果返回多个 id,就会报错。

应该使用:

复制代码
IN

错误二

FROM 子查询忘记别名。

错误:

复制代码
FROM
(
    SELECT ...
)

正确:

复制代码
FROM
(
    SELECT ...
) t

错误三

认为子查询一定慢。

现代数据库优化器会对很多子查询进行优化。

真正决定性能的是:

  • 索引

  • 数据量

  • 执行计划

而不是是否使用子查询。


十、本章总结

今天我们认识了 SQL 中的子查询:

  • 标量子查询(返回一个值)

  • 列子查询(返回一列)

  • 表子查询(返回一张临时表)

理解子查询之后,下一篇我们将学习 LeetCode 高频考点------EXISTS 与 NOT EXISTS,它们是判断数据是否存在的高效工具,也是面试中的经典知识点。

相关推荐
范什么特西10 小时前
回答知识总结04(redis)
数据库·redis·缓存
码农颜11 小时前
5.4.1 锁分类
java·数据库·mysql
云深处@12 小时前
【数据库】MySQL 入门
数据库·学习·mysql
梦远星帆12 小时前
SQLyog社区版下载
数据库·mysql·sqlyog
科力锐品牌君13 小时前
行业龙头|科力锐全链路防勒索 + 多中心容灾方案,构筑河南翔宇医疗业务安全闭环!
网络·数据库·分布式·安全·数据安全·备份
zyplayer-doc14 小时前
zyplayer-doc企业知识库能做什么:从文档创建、权限管理到AI问答的完整能力
大数据·javascript·数据库·人工智能·pdf·word
会编程的吕洞宾15 小时前
LangChain4j Tool Calling 实战:让大模型自动查数据库发邮件,一句话搞定复杂任务
数据库·人工智能
evans在进步16 小时前
LeetCode 2 两数相加:链表模拟加法,Java 图解进位过程
java·leetcode·链表
Hi李耶16 小时前
【LeetCode】557.反转字符串中的单词 III
算法·leetcode·职场和发展
知行合一。。。16 小时前
DeepAgents--01--Agent和OpenClaw的相关概念
android·数据库