Проблема при сравнении двойных значений с ISNULL - PullRequest
0 голосов
/ 02 января 2019

Я работаю над заданием, в котором мне нужно сравнить три поля выручки между двумя таблицами, и когда какие-либо из них отличаются, мне нужно обновить значение из таблицы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, я вижу, что он НЕ извлекает некоторые записи, которые необходимо обновить, если значения выручки равны NULL в таблице Product.

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?Или есть решение, позволяющее ускорить выполнение второго запроса?

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Вариант 1

Создайте 2 ТАБЛИЦЫ ТЕМПЕРАТУРЫ С dbo.Product OP И 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))
0 голосов
/ 02 января 2019

Кажется довольно очевидным, но каждый из них:

 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 не позволяет вашему запросу использовать какие-либо индексы для этих столбцов, в то время как этот более длинный кодовый блок будет использовать индексы и, следовательно, может быть быстрее.

...