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

时间:2019-02-24 11:12:14

标签: sql coalesce

我目前正在了解ISNULL和COALESCE之间的区别,并且遇到了一条声明:

COALESCE((<subquery), 0)

转换为(根据SQL标准):

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

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

1 个答案:

答案 0 :(得分: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)Microsoft或Sybase的某个人(曾有一段时间)实际上认为这是正确的方法。

(2)有人认为“我们已经具有执行此操作的功能,因此COALESCE()应该有所不同”。即使这种“小差异”使它看起来像被打破了。

(3)SQL Server不会通过仅运行一次子查询来优化子查询(据我所知)。因此,特别是对于子查询,想法可能是:“我们将在以后的优化中对此进行修复”。

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