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,它们是判断数据是否存在的高效工具,也是面试中的经典知识点。

相关推荐
千桐科技1 小时前
qData 数据中台开源版从 MySQL 到 Doris完成一次数据同步
大数据·mysql·开源·doris·数据中台·qdata
研究员子楚1 小时前
GEO行业发展标准体系白皮书V2.0-第10卷 · 全球篇:跨国标准协同与全球品牌语义治理框架
数据库·人工智能·microsoft·架构·geo
Omics Pro2 小时前
深度学习多组学互作:组内+组间
数据库·人工智能·深度学习·mysql·搜索引擎·自然语言处理
闪电悠米3 小时前
力扣hot100-56.合并区间-排序详解
数据结构·算法·leetcode·贪心算法·排序算法
残*影4 小时前
如何优雅地保存MySQL数据变更历史?
数据库·mysql
乐观的Terry4 小时前
3、数据库设计与领域实体
java·数据库·spring boot·spring cloud·ai编程
舞影天上4 小时前
RuoYi-Vue-Plus Docker 部署踩坑:MySQL 中文双重编码的根因与修复
数据库
卡提西亚4 小时前
leetcode-1438. 绝对差不超过限制的最长连续子数组
算法·leetcode·职场和发展
Database_Cool_4 小时前
数据仓库弹性扩缩容怎么实现?AnalyticDB MySQL 在线扩容 0 中断实战
数据库·数据仓库·mysql·阿里云