SQL中NOT IN与NOT EXISTS不等价的问题

 更新时间:2024年07月23日 08:59:46   作者:大橙子酸柠檬  
在对SQL语句进行性能优化时,经常用到一个技巧是将IN改写成EXISTS,本文主要介绍了SQL中NOT IN与NOT EXISTS不等价的问题,具有一定的参考价值,感兴趣的可以了解一下

在对SQL语句进行性能优化时,经常用到一个技巧是将IN改写成EXISTS,这是等价改写,并没有什么问题。问题在于,将NOT IN改写成NOT EXISTS时,结果未必一样。

执行环境:MySQL

一、举例验证

例如,有如下一张表 rr 。要求:选择4月2号的数据,并且其type1是4月1号没有的(从表看,就是4月2号C的那条)。

在这里插入图片描述

使用NOT IN ,单纯按照这个条件去实现

select * from rr 
where create_date='2024-04-02'
 and type1 not in (
		select type1 from rr 
		where create_date='2024-04-01'
	)
;

在这里插入图片描述

使用NOT EXISTS

select r1.* from rr as r1
where r1.create_date='2024-04-02'
 and not exists (
		select r2.type1 from rr as r2 
		where r2.create_date='2024-04-01' and r1.type1=r2.type1
	)
;

在这里插入图片描述

主要原因是4月1号的数据中,存在type1为NULL的。如果该type1不是NULL,使用NOT IN就可以正确找出来结果了。

其中的原理涉及三值逻辑

二、三值逻辑简述

以下的式子都会被判为unknown
1、 = NULL
2、> NULL
3、< NULL
4、<> NULL
NULL = NULL

unknown,它是因关系数据库采用了NULL而被引入的“第三个真值”。
(这里还有一点需要注意:真值unknown和作为NULL的一种UNKNOWN(未知)是不同的东西。前者是明确的布尔类型的真值,后者既不是值也不是变量。为了便于区分,前者采用粗体小写字母unknown,后者用普通的大写字母UNKNOWN表示。)

加上true和false,这三个真值之间有下面这样的优先级顺序。

  • AND 的情况:false > unknown > true
  • OR 的情况:true > unknown > false

下面看具体例子,连同unknown一起理解下

在这里插入图片描述

三、附录:用到的SQL

(运行环境Mysql)
1、表 rr 的构建

-- 使用了with语句
with rr as (
select '2024-04-01' as create_date,'A' as type1,001 as code1
 union all select '2024-04-01' as create_date,'A' as type1,002 as code1
 union all select '2024-04-01' as create_date,'A' as type1,002 as code1
 union all select '2024-04-01' as create_date,'B' as type1,013 as code1
 union all select '2024-04-01' as create_date,null as type1,013 as code1
 union all select '2024-04-02' as create_date,'B' as type1,013 as code1
 union all select '2024-04-02' as create_date,'C' as type1,109 as code1
 union all select '2024-04-03' as create_date,'A' as type1,002 as code1
 union all select '2024-04-04' as create_date,'A' as type1,002 as code1
)

2、 unknown的理解

set @a:=2, @b:=5, @c:= NULL ;

select @a+@b as result1,
       case when (@b>@c) is true then 'true!'
			      when (@b>@c) is false then 'false!'
			      else 'unknown'	
			 end as result2, -- 与NULL比较		 
       case when (@a<@b and @b>@c) is true then 'true!'
			      when (@a<@b and @b>@c) is false then 'false!'
			      else 'unknown'	
			 end as result3, -- and条件下 的优先级展示
			 case when (@a<@b or @b>@c) is true then 'true!'
			      when (@a<@b or @b>@c) is false then 'false!'
			      else 'unknown'	
			 end as result4, -- or条件下 的优先级展示
			 case when (not(@b<>@c)) is true then 'true!'
			      when (not(@b<>@c)) is false then 'false!'
			      else 'unknown'	
			 end as result5

到此这篇关于SQL中NOT IN与NOT EXISTS不等价的问题的文章就介绍到这了,更多相关SQL NOT IN与NOT EXISTS不等价内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 五种SQL Server分页存储过程的方法及性能比较

    五种SQL Server分页存储过程的方法及性能比较

    本文主要介绍了SQL Server数据库分页的存储过程的五种方法以及它们之间性能的比较,并给出了详细的代码,希望能够对您有所帮助。
    2015-08-08
  • 数据库 MySQL中文乱码解决办法总结

    数据库 MySQL中文乱码解决办法总结

    这篇文章主要介绍了数据库 MySQL中文乱码解决办法总结的相关资料,数据库保存中文字符,所以经常遇到数据库乱码情况,这里提供了几种方法,需要的朋友可以参考下
    2017-03-03
  • sqlserver 触发器实例代码

    sqlserver 触发器实例代码

    何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程
    2011-12-12
  • SQL 合并多行记录的方法总汇

    SQL 合并多行记录的方法总汇

    合并多行记录的方法,汇总。
    2009-06-06
  • MSSQL 2005/2008 日志压缩清理方法小结

    MSSQL 2005/2008 日志压缩清理方法小结

    本教程会详细介绍下MSSQL 2005和MSSQL 2008删除或压缩数据库日志的方法,感兴趣的朋友可以参考下哈,希望可以帮助到你
    2013-03-03
  • SQL Server驱动和TLS版本不兼容的原因分析和解决方案

    SQL Server驱动和TLS版本不兼容的原因分析和解决方案

    这篇文章主要介绍了在将Java程序部署到Docker容器时,由于SQL Server和OpenJDK 8之间的TLS/SSL版本不兼容问题导致的错误,通过修改`java.security`文件放宽TLS/SSL的安全限制,解决了本地服务器和Docker容器的兼容性问题,需要的朋友可以参考下
    2025-11-11
  • SQL语句中实现递归查询操作方法

    SQL语句中实现递归查询操作方法

    这篇文章给大家介绍SQL语句中实现递归查询操作方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2026-05-05
  • 在SQL SERVER 中用SSMS实现每日自动调用存储过程的操作步骤

    在SQL SERVER 中用SSMS实现每日自动调用存储过程的操作步骤

    在SSMS中通过SQL Server代理作业实现每日自动调用存储过程,需启用服务、创建作业并配置每日调度计划,注意权限与日志设置,测试验证后可扩展多步骤及失败通知功能,本文给大家介绍在SQL SERVER中用SSMS实现每日自动调用存储过程的操作步骤,感兴趣的朋友一起看看吧
    2025-08-08
  • sqlServer实现去除字符串空格

    sqlServer实现去除字符串空格

    简单的说SQL 中使用ltrim()去除左边空格 ,rtrim()去除右边空格 ,没有同时去除左右空格的函数,要去除所有空格可以用replace(字符串,' ',''),将字符串里的空格替换为空 。
    2017-01-01
  • SQLServer 优化SQL语句 in 和not in的替代方案

    SQLServer 优化SQL语句 in 和not in的替代方案

    用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
    2010-04-04

最新评论