Одна строка разрушает эффективность моего запроса? - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть простой запрос, который разбивает базу данных по номеру элемента, а затем вычисляет итоги для этих элементов

Вот как это выглядит.

SELECT DISTINCT

    Master_Item
    ,Item_Number
    ,'--' Color_Code 
    ,Description
    ,'--' Color_Description
    ,SUM(Unit_Retail) OVER (PARTITION BY Item_Number) Sum_Unit_Retail
    ,AVG(Unit_Retail) OVER (PARTITION BY Item_Number) Avg_Unit_Retail

    ,SUM(Unit_MarkDown) OVER (PARTITION BY Item_Number) Sum_Unit_MarkDown
    ,AVG(Unit_MarkDown) OVER (PARTITION BY Item_Number) Avg_Unit_MarkDown
    ,AVG(Unit_MarkDown_Percent) OVER (PARTITION BY Item_Number) Avg_Unit_MarkDown_Percent

    ,SUM(Sell_Price) OVER (PARTITION BY Item_Number) Sum_Sell_Price
    ,AVG(Sell_Price) OVER (PARTITION BY Item_Number) Avg_Sell_Price

    ,SUM(Discount_Value) OVER (PARTITION BY Item_Number) Sum_Discount_Value
    ,AVG(Discount_Value) OVER (PARTITION BY Item_Number) Avg_Discount_Value
    ,AVG(Unit_Discount_Value_Percent) OVER (PARTITION BY Item_Number) Avg_Discount_Value_Percent

    ,SUM(Sale_Price) OVER (PARTITION BY Item_Number) Sum_Sale_Price
    ,AVG(Sale_Price) OVER (PARTITION BY Item_Number) Avg_Sale_Price

    ,SUM(Royalty_Cost) OVER (PARTITION BY Item_Number) Sum_Royalty_Cost
    ,AVG(Royalty_Cost) OVER (PARTITION BY Item_Number) Avg_Royalty_Cost
    ,AVG(Unit_Royalty_Cost_Percent) OVER (PARTITION BY Item_Number) Avg_Royalty_Cost_Percent

    ,SUM(Item_Cost) OVER (PARTITION BY Item_Number) Sum_Item_Cost
    ,AVG(Item_Cost) OVER (PARTITION BY Item_Number) Avg_Item_Cost
    ,AVG(Unit_Item_Cost_Percent) OVER (PARTITION BY Item_Number) Avg_Item_Cost_Percent

    ,SUM(Order_Gross_Profit_Minus_Discounts_And_Royalty_And_Freight) OVER (PARTITION BY Item_Number) Sum_Order_Gross_Profit_Minus_Discounts_And_Royalty_And_Freight
    ,AVG(Order_Gross_Profit_Minus_Discounts_And_Royalty_And_Freight) OVER (PARTITION BY Item_Number) Avg_Order_Gross_Profit_Minus_Discounts_And_Royalty_And_Freight
    ,AVG(Order_Gross_Profit_Minus_Discounts_And_Royalty_And_Freight_Percent) OVER (PARTITION BY Item_Number) Avg_Order_Gross_Profit_Minus_Discounts_And_Royalty_And_Freight_Percent

    ,MAX(Quantity_Invoiced+Quantity_Allocated) OVER (PARTITION BY Item_Number) Max_Quantity

    ,SUM(Quantity_Invoiced+Quantity_Allocated) OVER (PARTITION BY Item_Number) Total_Units

    ,(DENSE_RANK() OVER (PARTITION BY Item_Number ORDER BY Customer_Purchase_Order_Number ASC) + DENSE_RANK() OVER (PARTITION BY Item_Number ORDER BY Customer_Purchase_Order_Number DESC) - 1) Total_Orders_Cont

    ,SUM(Quantity_Invoiced+Quantity_Allocated) OVER (PARTITION BY Item_Number) 
    / NULLIF((DENSE_RANK() OVER (PARTITION BY Item_Number ORDER BY Customer_Purchase_Order_Number ASC) + DENSE_RANK() OVER (PARTITION BY Item_Number ORDER BY Customer_Purchase_Order_Number DESC) - 1),0) Average_Order_Quantity

    ,SUM(Quantity_Returned) OVER (PARTITION BY Item_Number) Total_Units_Returned
    ,MAX(Quantity_Returned) OVER (PARTITION BY Item_Number) Max_Quantity_Returned
    ,SUM(Quantity_Returned) OVER (PARTITION BY Item_Number) 
    /NULLIF(SUM(Quantity_Invoiced+Quantity_Allocated) OVER (PARTITION BY Item_Number),0) Return_Percentage

    ,SUM(CASE WHEN F.Line_Status = 'CANCELLED' THEN Quantity_Ordered ELSE 0 END) OVER (PARTITION BY Item_Number) Cancelled_Count
    ,SUM(CASE WHEN F.Line_Status = 'CANCELLED' THEN Quantity_Ordered ELSE 0 END) OVER (PARTITION BY Item_Number) 
    / NULLIF(SUM(Quantity_Ordered) OVER (PARTITION BY Item_Number),0) Cancelled_Count_Percent

    ,SUM(CASE WHEN (Tags not like '%customerrequested_cancel%' and Tags not like '%ia_cancel%' and (FulfillmentState like 'partial%' or FinancialState like 'partial%')) THEN Short_Shipped ELSE 0 END) OVER (PARTITION BY Item_Number) Short_Shipped_Count
    ,SUM(CASE WHEN (Tags not like '%customerrequested_cancel%' and Tags not like '%ia_cancel%' and (FulfillmentState like 'partial%' or FinancialState like 'partial%')) THEN Short_Shipped ELSE 0 END) OVER (PARTITION BY Item_Number) 
    / NULLIF(SUM(Quantity_Ordered) OVER (PARTITION BY Item_Number),0) Short_Shipped_Count_Percent

FROM 
    FinalEcomTable F

WHERE
    1=1
    AND (F.Company_Code = '09' OR '09' IS NULL)  
    AND (F.Division_Code = '001' OR '001' IS NULL)
    AND COALESCE(F.Shopify_Ordered ,F.Date_Entered) BETWEEN '1/1/2018' AND DATEADD(dayofyear, 1, '9/1/2019')

Этот запрос занимает одинсекунда до запуска.

Однако, как только я добавлю следующие строки

    ,(DENSE_RANK() OVER (PARTITION BY Item_Number ORDER BY Customer_Purchase_Order_Number ASC) + DENSE_RANK() OVER (PARTITION BY Item_Number ORDER BY Customer_Purchase_Order_Number DESC) - 1) 
    / NULLIF(SUM(CASE WHEN F.Order_Status <> 'CANCELLED' AND F.Odet_Line_Number = 1 THEN 1 ELSE 0 END) OVER () ,0) Percent_Of_Orders_Cont

Этот запрос переходит от 1 секунды к 15 секундам.

Проблема в линии делителя

(SUM(CASE WHEN F.Order_Status <> 'CANCELLED' AND F.Odet_Line_Number = 1 THEN 1 ELSE 0 END) OVER ())

Потому что, если я попытаюсь запустить эту строку отдельно, это займет очень много времени.

Есть ли способ переписать эту строку, чтобы сделать ее более эффективной или оптимизированной?Кто-нибудь знает, почему он так себя ведет?Это потому, что я меняю раздел с Item_number на все?

Вот план выполнения без строки с ошибками:

https://www.brentozar.com/pastetheplan/?id=H1dVjXbDS

А вот с строкой с ошибками, помещенной обратно в:

https://www.brentozar.com/pastetheplan/?id=SJy7hXWPr

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...