文章目录

  • 零、前言
  • 一、练习题目
  • 二、SQL思路
  • 初始化数据
  • 什么是Double Not Exists
  • 实战体验
  • 方案一:
  • 方案二:
  • 方案三:
  • 三、总结
  • 四、参考


零、前言

今天是学习 SQL 打卡的第 36 天。

我的学习策略很简单,题海策略+ 费曼学习法。如果能把这些题都认认真真自己实现一遍,那意味着 SQL 已经筑基成功了。后面的进阶学习,可以继续跟着我,一起走向架构师之路。

今天的学习内容是:SQL高级技巧-Double Not Exists

一、练习题目

题目链接

难度

Double Not Exists Check

★★★☆☆

二、SQL思路

【第36天】SQL进阶-SQL高级技巧-Double Not Exists(SQL 小虚竹)_子查询


【第36天】SQL进阶-SQL高级技巧-Double Not Exists(SQL 小虚竹)_子查询_02

初始化数据

创建表结构:有两个表: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用于检查订单是否已经被取消。只有当订单既没有发货记录也没有被取消时,它才会被选中。

【第36天】SQL进阶-SQL高级技巧-Double Not Exists(SQL 小虚竹)_sql_03

方案二:

是使用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”的订单。

【第36天】SQL进阶-SQL高级技巧-Double Not Exists(SQL 小虚竹)_数据库_04

方案三:

另一个解决方案是使用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”。

【第36天】SQL进阶-SQL高级技巧-Double Not Exists(SQL 小虚竹)_sql_05

三、总结

Double Not Exists是SQL查询中常见的一个问题,它涉及到如何有效地处理多个否定条件。虽然直接使用两个NOT EXISTS可能看起来直观,但通常不是最优的解决方案。通过使用LEFT JOIN或NOT IN结合子查询,我们可以更高效地解决这类问题。

所以,嗯,这题的答案选。。评论区大声告诉虚竹哥。

四、参考

我是虚竹哥,我们明天见~