将双精度值与ISNULL

时间:2019-01-02 20:26:47

标签: sql-server query-optimization 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表具有值,但是当我将double值与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行。第一个查询在不到一分钟的时间内返回了结果。

是否存在将double值与NULL比较的替代解决方案?还是有一种解决方案可以使第二个查询运行更快?

2 个答案:

答案 0 :(得分:4)

似乎很明显,但其中每一个:

 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 :(得分:0)

选项1

使用dbo.Product OP和dbo.Product_Working OPW创建2个TEMP表。创建两个表时都使用nullull

例如

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))