《LeetCode SQL 从入门到进阶(MySQL)》06(下)

EXISTS 与 NOT EXISTS,一篇彻底搞懂存在性查询

大家好,欢迎来到《LeetCode SQL 从入门到进阶(MySQL)》专栏。

上一篇我们学习了子查询(Subquery)的基本使用方法,本篇继续学习另一类在 LeetCode 和实际开发中都非常重要的知识------EXISTS 与 NOT EXISTS

很多初学者知道 IN,却不知道什么时候应该使用 EXISTS。事实上,它们虽然都可以完成类似的查询,但执行思路完全不同。


一、什么是 EXISTS?

EXISTS 的作用非常简单:

判断子查询是否能够返回至少一条记录。

语法:

复制代码
SELECT ...
FROM 表A
WHERE EXISTS (
    SELECT 1
    FROM 表B
    WHERE ...
);

如果子查询能够返回数据,则 EXISTS 返回 TRUE;否则返回 FALSE。


二、一个简单例子

员工表:

id name
1 Alice
2 Bob
3 Tom

订单表:

id employeeId
1 1
2 1
3 3

现在要求:

查询至少拥有一个订单的员工。

可以写:

复制代码
SELECT *
FROM Employee e
WHERE EXISTS (
    SELECT 1
    FROM Orders o
    WHERE o.employeeId = e.id
);

执行过程:

对于 Alice:

复制代码
Orders 中是否存在 employeeId=1?
有。

因此保留。

对于 Bob:

复制代码
Orders 中是否存在 employeeId=2?
没有。

因此过滤。

对于 Tom:

复制代码
Orders 中是否存在 employeeId=3?
有。

因此保留。

最终得到:

name
Alice
Tom

三、为什么写 SELECT 1?

很多人第一次都会疑惑:

复制代码
SELECT 1

为什么不是:

复制代码
SELECT *

实际上:

对于 EXISTS 来说,

数据库并不关心返回什么内容

它只关心:

有没有记录。

因此:

复制代码
SELECT 1

SELECT *

SELECT id

效果完全一样。

一般推荐:

复制代码
SELECT 1

表达:

我只是判断是否存在。


四、NOT EXISTS

NOT EXISTS 就是:

不存在。

例如:

查询没有任何订单的员工。

复制代码
SELECT *
FROM Employee e
WHERE NOT EXISTS (
    SELECT 1
    FROM Orders o
    WHERE o.employeeId = e.id
);

最终得到:

name
Bob

五、EXISTS 与 IN 的区别

例如:

复制代码
SELECT *
FROM Employee
WHERE id IN (
    SELECT employeeId
    FROM Orders
);

和:

复制代码
SELECT *
FROM Employee e
WHERE EXISTS (
    SELECT 1
    FROM Orders o
    WHERE o.employeeId=e.id
);

都能得到相同结果。

区别在于:

IN

更像:

先把子查询所有结果取出来,再判断是否属于这个集合。

EXISTS

更像:

找到第一条符合条件的数据后立即停止。

因此:

当子查询数据很多时,

EXISTS 往往更高效。


六、相关子查询

注意:

复制代码
WHERE o.employeeId=e.id

这里:

子查询引用了外层查询的:

复制代码
e.id

这种写法叫:

相关子查询(Correlated Subquery)

它是 EXISTS 最常见的使用方式。


七、LeetCode 常见应用

常见题型:

  • 查询存在订单的用户

  • 查询没有登录过的用户

  • 查询购买过商品的顾客

  • 查询未参加考试的学生

基本都可以想到:

复制代码
EXISTS

或者:

复制代码
NOT EXISTS

八、常见错误

错误一

忘记关联条件。

错误:

复制代码
WHERE EXISTS (
    SELECT 1
    FROM Orders
)

因为:

只要 Orders 非空,

所有员工都会返回。

正确:

复制代码
WHERE EXISTS (
    SELECT 1
    FROM Orders o
    WHERE o.employeeId=e.id
)

错误二

把 EXISTS 和 IN 混用。

例如:

复制代码
WHERE EXISTS (
    SELECT employeeId
)

EXISTS 不关心返回哪一列。

真正重要的是:

子查询能否返回记录。


九、本章总结

今天学习了:

  • EXISTS:存在至少一条记录。

  • NOT EXISTS:不存在任何记录。

  • EXISTS 常与相关子查询一起使用。

  • EXISTS 判断存在性,IN 判断是否属于集合。

掌握 EXISTS 后,你已经具备解决绝大多数存在性查询问题的能力。

下一篇,我们将进入字符串处理部分,学习 MySQL 中最常见的字符串函数。

相关推荐
zandy10112 小时前
多租户SaaS架构下的BI数据隔离与权限治理体系
数据库·架构·数据加密
多巴胺梦想家2 小时前
NoSQL 数据库:不只是关系型
数据库·nosql
数字孪生家族3 小时前
3DGS 数据编辑单体化技术:将高斯重建转化为结构化数字空间资产
数据库·3d·高斯泼溅·空间智能应用
广州灵眸科技有限公司3 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) 系统操作-线进程操作
数据库·单片机·嵌入式硬件·算法·php
石一峰6994 小时前
驱动:私有数据为什么要在三个地方各挂一遍?
数据库·python·算法
ClouGence5 小时前
跨云、跨地域数据同步,这样更省心
数据库·sql·saas
TDengine (老段)5 小时前
TDengine 函数完整参考 — 聚合、时序、字符串、时间、数学
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
TDengine (老段)6 小时前
昆仑数智选择 TDengine TSDB,提升页岩气生产运行可视化与精细化管理能力
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
陆水A6 小时前
【问数系统】SQL跑对了图表却空了?打通问数系统最后1公里的3个API坑
大数据·数据库·自然语言处理·big data·etl工程师