我目前正在了解ISNULL和COALESCE之间的区别,并且遇到了一条声明:
COALESCE((<subquery), 0)
转换为(根据SQL标准):
CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
我的问题是:为什么子查询执行两次?这似乎效率低下。
答案 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不会通过仅运行一次子查询来优化子查询(据我所知)。因此,特别是对于子查询,想法可能是:“我们将在以后的优化中对此进行修复”。
这都是猜测(因此有观点)。我想回答,因为这不仅会影响子查询。