将双精度值与 ISNULL 进行比较时出现问题



我正在做一项作业,我需要比较两个表之间的三个收入字段,当它们中的任何一个不同时,我需要将表1的值更新到表2中。

我的更新查询如下。

UPDATE OP
SET OP.CompCanceledRevenue = OPW.Comp_Canceled_Revenue__c,
    OP.PriorYearOperatingRevenueAmt = OPW.PriorYearRevenueAmount,
    OP.YTDOperatingRevenueAmt = OPW.YTDRevenueAmount,
FROM dbo.Product OP
INNER JOIN dbo.Product_Working OPW ON OPW.ProductCode = OP.ProductCode
                                   AND (OP.CompCanceledRevenue <> OPW.Comp_Canceled_Revenue__c
                                        OR OP.PriorYearOperatingRevenueAmt <> OPW.PriorYearRevenueAmount
                                        OR OP.YTDOperatingRevenueAmt <> OPW.YTDRevenueAmount)

当我在 SQL Server 中运行此查询时,我看到它没有提取一些需要更新的记录,其中Product表中的收入值为 NULL。

Product_Working表都有值,但是当我将双精度值与 NULL 进行比较时<>条件似乎不起作用。所以我更改了我的查询,如下所示。

UPDATE OP
SET OP.CompCanceledRevenue = OPW.Comp_Canceled_Revenue__c,
    OP.PriorYearOperatingRevenueAmt = OPW.PriorYearRevenueAmount,
    OP.YTDOperatingRevenueAmt = OPW.YTDRevenueAmount,
FROM dbo.Product OP
INNER JOIN dbo.Product_Working OPW ON OPW.ProductCode = OP.ProductCode
                                   AND (ISNULL(OP.CompCanceledRevenue, 0) <> ISNULL(OPW.Comp_Canceled_Revenue__c, 0)
                                        OR ISNULL(OP.PriorYearOperatingRevenueAmt, 0) <> ISNULL(OPW.PriorYearRevenueAmount, 0)
                                        OR ISNULL(OP.YTDOperatingRevenueAmt, 0) <> ISNULL(OPW.YTDRevenueAmount, 0))

此查询返回我想要的结果,但需要 1 个多小时才能完成。Product表有 500,000 行,Product_Working表有大约 250,000 行。第一个查询在不到一分钟的时间内返回结果。

是否有替代解决方案将双精度值与 NULL 进行比较?或者是否有解决方案可以使第二个查询运行得更快?

看起来很明显,但这些中的每一个:

 ISNULL(OP.CompCanceledRevenue,0) <> ISNULL(OPW.Comp_Canceled_Revenue__c,0)

可以改写为:

 (
  OP.CompCanceledRevenue <> OPW.Comp_Canceled_Revenue__c
  OR (OP.CompCanceledRevenue IS NULL AND OPW.Comp_Canceled_Revenue__c IS NOT NULL)
  OR (OP.CompCanceledRevenue IS NOT NULL AND OPW.Comp_Canceled_Revenue__c IS NULL)
 )

直观地说,您可能会期望这会更慢,因为它是更多的代码,但实际上,ISNULL 函数会阻止您的查询在这些列上使用任何索引,而这个较长的代码块将使用索引,因此可能会更快。

选项 1

使用 DBO 创建 2 个临时表。产品操作和 dbo。Product_Working OPW。创建两个表时使用 isnull

前任。

Select *
      ,isnull(PriorYearOperatingRevenueAmt) as PriorYearOperatingRevenueAmt_n
      ,isnull(YTDOperatingRevenueAmt) as YTDOperatingRevenueAmt_n
into ##tmpprod
from dbo.Product

对两个表执行相同的操作并联接它们。

选项 2将您的条件放在 where 子句上

UPDATE OP
        SET OP.CompCanceledRevenue = OPW.Comp_Canceled_Revenue__c,
              OP.PriorYearOperatingRevenueAmt = OPW.PriorYearRevenueAmount,
              OP.YTDOperatingRevenueAmt = OPW.YTDRevenueAmount,
        FROM dbo.Product OP
        INNER JOIN dbo.Product_Working OPW 
        ON OPW.ProductCode = OP.ProductCode
Where
 ( ISNULL(OP.CompCanceledRevenue,0) <> ISNULL(OPW.Comp_Canceled_Revenue__c,0)
        OR ISNULL(OP.PriorYearOperatingRevenueAmt,0) <> ISNULL(OPW.PriorYearRevenueAmount,0)
        OR ISNULL(OP.YTDOperatingRevenueAmt,0) <> ISNULL(OPW.YTDRevenueAmount,0))

最新更新