3 回答

TA贡献1789条经验 获得超10个赞
Microsoft Connect上报告的此问题揭示了COALESCE和之间的一些区别ISNULL:
我们处理的早期部分重写COALESCE( expression1, expression2 )为CASE WHEN expression1 IS NOT NULL THEN expression1 ELSE expression2 END。在[此示例]中:
COALESCE ( ( SELECT Nullable
FROM Demo
WHERE SomeCol = 1 ), 1 )
我们生成:
SELECT CASE
WHEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) IS NOT NULL
THEN (SELECT Nullable FROM Demo WHERE SomeCol = 1)
ELSE 1
END
查询处理的后期阶段不了解这两个子查询原本是相同的表达式,因此它们执行了两次子查询...
尽管我不愿提出建议,但一种解决方法是将更COALESCE改为ISNULL,因为后者不会复制子查询。

TA贡献1809条经验 获得超8个赞
值得一提的是,两者之间的类型处理也可以有所作为(请参阅此相关答案项(2))。
假设查询尝试使用快捷方式编写空比较:
select * from SomeTable
where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);
不同于
select * from SomeTable
where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);
因为在第一种情况下,IsNull()强制类型为一点(因此将-1转换为true),而在第二种情况下,两者都会提升为int值。
with input as
(
select convert(bit, 1) as BitOn,
convert(bit, 0) as BitOff,
convert(bit, null) as BitNull
)
select BitOn,
BitOff,
BitNull,
IsNull(BitOn, -1) IsNullBitOn, -- true
IsNull(BitOff, -1) IsNullBitOff, -- false
IsNull(BitNull, -1) IsNullBitNull, -- true, converts the -1 to bit
coalesce(BitOn, -1) CoalesceBitOn, -- 1
coalesce(BitOff, -1) CoalesceBitOff, -- 0
coalesce(BitNull, -1) CoalesceBitNull -- -1
from input;
问题本身也有类似的评论/链接(@Martin Smith)。
- 3 回答
- 0 关注
- 714 浏览
添加回答
举报