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

相关推荐
李兆龙的博客11 小时前
问津集 #26:Lakebase——Postgres 的版本化页面存储、数据库分支与计算弹性
数据库
yi01111 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
倔强的石头_13 小时前
聊聊金仓KFS:一款把数据同步软件做扎实的产品
数据库
闲云野鹤在人间13 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算
禾小西13 小时前
Redis:从两大维度和三大主线建立知识体系
数据库·redis·缓存
禾小西14 小时前
Redis 数据结构:快速的 Redis 有哪些慢操作?
数据结构·数据库·redis
数据库小学妹14 小时前
数据共享交换平台选型:交换方式对比与避坑指南
数据库·信创·数据同步·数据交换平台·政务数据共享·数据共享交换平台·数据库底座
要开心吖ZSH14 小时前
MySQL 慢 SQL 排查操作手册-个人笔记版
java·笔记·sql·mysql·慢查询
好想像大佬一样能够ak所有15 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
aqiu11111115 小时前
【C++算法打怪专栏】LeetCode 165. 比较版本号(双指针与字符串流法)
c++·算法·leetcode