当前位置: 代码网 > it编程>数据库>MsSqlserver > SQL中NOT IN与NOT EXISTS不等价的问题

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

2024年07月23日 MsSqlserver 我要评论
在对sql语句进行性能优化时,经常用到一个技巧是将in改写成exists,这是等价改写,并没有什么问题。问题在于,将not in改写成not exists时,结果未必一样。执行环境:mysql一、举例

在对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不等价内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com