为什么COALESCE执行子查询两次?

问题描述 投票:0回答:1

我目前正在了解ISNULL和COALESCE之间的区别,我发现一条声明说:

COALESCE((<subquery), 0)

被翻译成(根据SQL标准):

CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END

我的问题是:为什么子查询执行了两次?这似乎效率低下。

sql coalesce
1个回答
1
投票

ISNULL()与SQL Server相关联,因此这个问题似乎与SQL Server有关。正如评论中指出的那样,SQL Server运行子查询两次。

顺便说一句,这可能是恶化的 - 而不仅仅是子查询。请考虑以下表达式:

select coalesce(case when rand(checksum(newid())) < 0.5 then 'a' end, 'b')

它可以返回NULL值 - 尽管COALESCE(),因为第一个表达式被评估两次。为了好玩,您可以运行此查询:

select v.n, coalesce(case when rand(checksum(newid())) < 0.5 then 'a' end, 'b')
from (values (1), (2), (3), (4), (5), (6), (7), (8)) v(n);

我可以推测SQL Server以这种方式运行的几个原因。

(1)微软或Sybase的人(曾几何时)实际上认为这是正确的方法。

(2)有人认为“我们已经有了这样做的功能,所以COALESCE()应该有点不同”。即使这种“微小的差异”使它看起来像是破碎了。

(3)SQL Server不会通过仅运行一次来​​优化子查询(据我所知)。因此,对于子查询,特别是这个想法可能是:“我们将在后一轮优化中解决这个问题”。

这都是猜测(因此也是意见)。我想回答,因为这不仅会影响子查询。

© www.soinside.com 2019 - 2024. All rights reserved.