文章目录
- 零、前言
- 一、练习题目
- 二、SQL思路
- 初始化数据
- 什么是Double Not Exists
- 实战体验
- 方案一:
- 方案二:
- 方案三:
- 三、总结
- 四、参考
零、前言
今天是学习 SQL 打卡的第 36 天。
我的学习策略很简单,题海策略+ 费曼学习法。如果能把这些题都认认真真自己实现一遍,那意味着 SQL 已经筑基成功了。后面的进阶学习,可以继续跟着我,一起走向架构师之路。
今天的学习内容是:SQL高级技巧-Double Not Exists
一、练习题目
题目链接 | 难度 |
Double Not Exists Check | ★★★☆☆ |
二、SQL思路
初始化数据
创建表结构:有两个表:orders(订单表)和shipments(发货表)。
CREATE TABLE orders (
order_id INT PRIMARY KEY,
order_status VARCHAR(50) NOT NULL
);
CREATE TABLE shipments (
shipment_id INT PRIMARY KEY,
order_id INT,
FOREIGN KEY (order_id) REFERENCES orders(order_id)
);
插入测试数据的SQL
INSERT INTO orders (order_id, order_status) VALUES
(1, 'Pending'),
(2, 'Shipped'),
(3, 'Cancelled'),
(4, 'Pending');
INSERT INTO shipments (shipment_id, order_id) VALUES
(1, 2),
(2, 2);
什么是Double Not Exists
Double Not Exists是指在SQL查询中,我们需要同时满足两个或多个“不存在”的条件。这通常发生在需要基于两个或多个子查询的否定条件来过滤结果时。然而,直接使用两个NOT EXISTS可能会导致逻辑上的混淆或查询性能的下降。
实战体验
例子:找出那些既没有发货也没有取消的订单
方案一:
使用 Double Not Exists
SELECT
O.ORDER_ID
FROM
ORDERS O
WHERE
NOT EXISTS (
SELECT
1
FROM
SHIPMENTS S
WHERE
S.ORDER_ID = O.ORDER_ID
)
AND NOT EXISTS (
SELECT
1
FROM
ORDERS O2
WHERE
O2.ORDER_ID = O.ORDER_ID
AND O2.ORDER_STATUS = 'CANCELLED'
);
在这个查询中,我们使用了两个嵌套的NOT EXISTS子句。第一个NOT EXISTS用于检查订单是否有发货记录,第二个NOT EXISTS用于检查订单是否已经被取消。只有当订单既没有发货记录也没有被取消时,它才会被选中。
方案二:
是使用LEFT JOIN或NOT IN结合子查询来替代Double Not Exists。
SELECT
O.ORDER_ID
FROM
ORDERS O
LEFT JOIN SHIPMENTS S ON
O.ORDER_ID = S.ORDER_ID
WHERE
S.ORDER_ID IS NULL
AND O.ORDER_STATUS <> 'CANCELLED';
这个查询首先通过LEFT JOIN将orders表和shipments表连接起来,然后通过WHERE子句筛选出那些没有发货记录(s.order_id IS NULL)且订单状态不是“Cancelled”的订单。
方案三:
另一个解决方案是使用NOT IN结合子查询
SELECT
ORDER_ID
FROM
ORDERS
WHERE
ORDER_ID NOT IN (
SELECT
ORDER_ID
FROM
SHIPMENTS)
AND ORDER_STATUS <> 'CANCELLED';
这个查询首先通过子查询找出所有有发货记录的订单ID,然后在orders表中筛选出那些ID不在这个列表中的订单,并且订单状态不是“Cancelled”。
三、总结
Double Not Exists是SQL查询中常见的一个问题,它涉及到如何有效地处理多个否定条件。虽然直接使用两个NOT EXISTS可能看起来直观,但通常不是最优的解决方案。通过使用LEFT JOIN或NOT IN结合子查询,我们可以更高效地解决这类问题。
所以,嗯,这题的答案选。。评论区大声告诉虚竹哥。
四、参考
我是虚竹哥,我们明天见~