如何在SQL中将NOT IN语句转换为NOT EXISTS语句?
我听说应该不惜一切代价避免如何在SQL中将NOT IN语句转换为NOT EXISTS语句?,sql,postgresql,Sql,Postgresql,我听说应该不惜一切代价避免不在中,因此我正在更新我的查询,以利用不存在并对它们运行解释分析,以查看是否有任何改进,但我很难对其进行认真思考。如何转换这样的查询: 选择id 来自客户c 其中c.状态不在 (“已删除”、“已存档”、“已过期”) 如果将not in与嵌套选择一起使用,则可能是正确的,例如: select id from customer c where c.status_id not in ( select id from status s where s.t
不在
中,因此我正在更新我的查询,以利用不存在
并对它们运行解释分析
,以查看是否有任何改进,但我很难对其进行认真思考。如何转换这样的查询:
选择id
来自客户c
其中c.状态不在
(“已删除”、“已存档”、“已过期”)
如果将not in
与嵌套选择一起使用,则可能是正确的,例如:
select id
from customer c
where c.status_id not in (
select id
from status s
where s.type = 'DELETED'
)
这应该改写为:
select id
from customer c
where not exists(
select *
from status s
where (s.id, s.type) = (c.status_id, 'DELETED')
)
但是,由于您正在使用带有一组可能值的
not in
,因此使用exists
重写它是正常的,如果您使用嵌套选择的not in
,则可能是正确的,例如:
select id
from customer c
where c.status_id not in (
select id
from status s
where s.type = 'DELETED'
)
这应该改写为:
select id
from customer c
where not exists(
select *
from status s
where (s.id, s.type) = (c.status_id, 'DELETED')
)
但是,由于您正在使用not in
和一组可能的值,所以这没关系,而且使用exists
重写它甚至很困难
我听说应该不惜一切代价避免
不在中
你听错了——你在生产中应用了一些你不理解的东西(或者你在没有任何调查的情况下表面上接受的东西)。你所说的就是一个例子。不要这样做。不要相信没有引用和来源的任何东西(顺便说一句,这适用于生活中的一切)
无论如何,不在
和不存在
在语义上是不等价的:在
中(和不在
中)当与可变文字值或可变参数一起使用时,只是重复的或
语句的语法糖,而不存在
是对集合成员资格的测试,这是一个非常不同的操作
就您而言,这是:
WHERE c.status NOT IN ('DELETED', 'ARCHIVED', 'EXPIRED')
在语义上与此相同:
…这样一个表达式不能简化,我认为它是最优的
因此:不需要对此查询进行任何更改
我听说应该不惜一切代价避免不在中
你听错了——你在生产中应用了一些你不理解的东西(或者你在没有任何调查的情况下表面上接受的东西)。你所说的就是一个例子。不要这样做。不要相信没有引用和来源的任何东西(顺便说一句,这适用于生活中的一切)
无论如何,不在
和不存在
在语义上是不等价的:在
中(和不在
中)当与可变文字值或可变参数一起使用时,只是重复的或
语句的语法糖,而不存在
是对集合成员资格的测试,这是一个非常不同的操作
就您而言,这是:
WHERE c.status NOT IN ('DELETED', 'ARCHIVED', 'EXPIRED')
在语义上与此相同:
…这样一个表达式不能简化,我认为它是最优的
因此:不需要对此查询进行任何更改。您不完全了解该规则。这是错误的:
我听说无论如何都应该避免不在
这更接近于事实:
我听说无论如何都应该避免不使用子查询
这有两个原因。到目前为止,更重要的是处理NULL
值。如果子查询返回的任何值为NULL
,则notin
永远不会返回TRUE
。也就是说,查询不返回任何行(如果这是唯一的条件)
另一方面,notexists
实现了您在本例中所期望的功能,基本上忽略了子查询中的NULL
值
这不是显式列表的问题,因为在显式列表中不太可能包含NULL
值
第二个问题是性能。一些数据库将使用子查询优化不存在
,比不存在
要好得多——特别是在适当的索引可用的情况下。您不完全了解规则。这是错误的:
我听说无论如何都应该避免不在
这更接近于事实:
我听说无论如何都应该避免不使用子查询
这有两个原因。到目前为止,更重要的是处理NULL
值。如果子查询返回的任何值为NULL
,则notin
永远不会返回TRUE
。也就是说,查询不返回任何行(如果这是唯一的条件)
另一方面,notexists
实现了您在本例中所期望的功能,基本上忽略了子查询中的NULL
值
这不是显式列表的问题,因为在显式列表中不太可能包含NULL
值
第二个问题是性能。一些数据库将使用子查询优化不存在
,这比不在
中要好得多——特别是在适当的索引可用的情况下。“我听说应该不惜一切代价避免不在
中”-你从哪里听说的?我不同意那种说法。记住,所有的概括都是错误的,包括这个!“不惜一切代价”可能是言过其实,我应该更仔细地表达。这更像是一种“使用<代码>不在<代码>中时要小心”的建议,实际上,对于您来说,问题中提到的查询“不在”已经足够好了。当您在where子句中使用子查询来检查value@AkhileshMishra实际的查询在
和
语句中有一点拥挤,但我不想在不混淆所有内容的情况下发布原始查询,因此,我发布了一个简化版本。我不知道postgres的优化,但IME与其他产品的问题是不在