Coalesce(),ISNULL()澄清

时间:2014-04-27 10:07:56

标签: sql sql-server

我目前正在攻读我的MCSA数据平台,我得到了以下错误的问题,我正在寻找一个解释,为什么我的答案是错误的,因为测试解释没有多大意义。

Hovercraft Wages表记录了Contoso工人的工资。工人可以获得每日工资或年薪。该表包含以下列:

EmpID,Daily_Rate,Yearly_Salary

工人只获得一种收入率,而其记录中的另一列的值为NULL。您希望运行一个查询来计算每个员工的总薪水,假设人们每周工作5天,每年52周。

下面是两个选项,正确答案和我选择的答案

SELECT EmpID, CAST(COALESCE(Daily_Rate*5*52, Yearly_Salary) AS money) AS 'Total Salary'
FROM Hovercraft.Wages;

SELECT EMPID, CAST(ISNULL(Daily_Rate*5*52, Yearly_Salary)AS money)AS 'Total Salary'
FROM Hovercraft.Wages;

我选择了第二个选项,因为只有两个可能的付费字段,但被标记为合并不正确,任何人都可以澄清为什么ISNULL在这个例子中不是一个有效的选择,因为我不想在这个例子中犯这个错误将来

非常感谢

2 个答案:

答案 0 :(得分:3)

最大的区别是ISNULL是专有的,而COALESCE是SQL标准的一部分。认证课程可以教授最大程度的知识可移植性,因此当您有多种选择时,课程更喜欢解决问题的标准方法。

在这种情况下可能重要的另一个差异是数据类型确定。 ISNULL使用第一个参数的类型,而COALESCE遵循与CASE相同的规则,并选择具有更高优先级的类型。当Daily_Rate存储在范围较窄的列中时,这可能很重要。

为了完整性,这里列出了两者之间的其他差异(taken from Microsoft SQL Server Blog):

  • 结果表达式的可用性不同,
  • ISNULLCOALESCE的验证不同,因为NULL的{​​{1}}值已转换为ISNULL,但int会触发错误}
  • COALESCE仅使用两个参数,而ISNULL采用可变数量的参数
  • 您可以为这两个功能获得不同的查询计划。

编辑:从答案措辞的方式来看,我认为作者希望您在第二个参数保证为非NULL的情况下使用COALESCE,例如:不可空的字段或常量。虽然通常这个想法是合理的,但是他们选择测试它的问题并不理想:问题是问题保证第二个ISNULL参数的值在重要的情况下是非NULL的,这使得两个选择在逻辑上等同。

答案 1 :(得分:0)

除了所有众所周知的差异之外,没有多少人知道COALESCE只是CASE的简写,并且继承了所有这些&#s; s和-s - 列表参数,适当的结果铸造等。

但对于一个毫无戒心的开发者来说,这也可能是性能的下降。

为了证明我的观点,请运行这三个查询(在AdventureWorks2012数据库上)并检查它们的执行计划:

SELECT COALESCE((SELECT CustomerID FROM Sales.SalesOrderHeader WHERE SalesOrderId = 57418), 0)

SELECT ISNULL((SELECT CustomerID FROM Sales.SalesOrderHeader WHERE SalesOrderId = 57418), 0)

SELECT CASE WHEN (SELECT CustomerID FROM Sales.SalesOrderHeader WHERE SalesOrderId = 57418) IS NULL 
    THEN 0
    ELSE (SELECT CustomerID FROM Sales.SalesOrderHeader WHERE SalesOrderId = 57418)
END

您会看到第一个和第三个具有相同的执行计划(因为COALESCE只是CASE的简短形式)。另外,您会看到在第一个和第三个查询中,SalesOrderHeader表被访问两次,因为ISNULL只使用了一次。

如果您还为会话启用了SET STATISTICS IO ON,那么您会注意到这两个查询的逻辑读取次数是两倍。

在这种情况下,COALESCE执行了两次内部SELECT语句,而ISNULL只执行了一次。这可能会产生巨大的差异。