Мне было поручено улучшить производительность хранимой процедуры, которая использует UNION ALL из двух операторов для получения желаемых результатов. В своих путешествиях я наткнулся на идею использования WITH ROLLUP в качестве альтернативы для повышения производительности. Я неплохо разбираюсь в SQL, но думаю, мне нужна небольшая помощь с этим. (Я тоже здесь новичок, поэтому я не так знаком с Db, как хотелось бы.)

Он выбирается в основном из одних и тех же мест в обоих операторах, как вы можете видеть по объединениям. Но условия у них немного разные. Одно соединение во втором операторе имеет <> 'zzzCUSTOM', но, например, в соответствующем первом операторе этого нет. Я думаю, что есть лучший способ написать это, чтобы не использовать UNION ALL, возможно, объединив условия / соединения в один оператор, поскольку все это в любом случае складывается вместе (UNION ALL)? ... Другие идеи ?

Хранимая процедура также построена с использованием динамического SQL, поэтому уследить за ней непросто. Вот как обычный SQL (со всеми заполненными переменными):

SELECT 
    [SKU No], [SKN], [Description], [Orders], 
    [Quantity], [Unit Price], [Total Price] 
FROM 
    (SELECT 
         1 AS TOT, 
         'Totals:' AS [SKU No], 
         '' AS [SKN], 
         '' AS [DESCRIPTION], 
         isnull(SUM([Orders]), 0) AS [Orders], 
         isnull(SUM([Quantity]), 0) AS [Quantity], 
         isnull(SUM([Unit Price]), 0) AS [Unit Price], 
         isnull(SUM([Total Price]), 0) AS [Total Price] 
     FROM 
         (SELECT 
              COUNT(distinct o.orderno) AS [Orders], 
              SUM(oi.quantity) as [Quantity], 
              oi.unitprice AS [Unit Price], 
              SUM(oi.extprice) AS [Total Price] 
          FROM
              orderupdates ou  
          INNER JOIN 
              orders o ON o.orderno = ou.orderno 
          INNER JOIN 
              orderdetails od ON od.orderno = o.orderno 
          INNER JOIN 
              orderitems oi ON oi.orderno = o.orderno 
                            AND oi.linenum = od.linenum 
          INNER JOIN 
              items i ON i.itemid = od.itemid 
          WHERE
              actdate >= '2015-05-01' 
              AND ou.actdate < '2015-05-15' 
              AND type = 0 
          GROUP BY
              oi.unitprice, i.skuno, i.description) S 

    union all 

    select 0 AS TOT, 
        isnull(i.skuno,'') as [SKU No], 
        isnull(vi.SKUNo,'')AS [SKN], 
        isnull(i.description,'')AS [DESCRIPTION], 
        count(distinct o.orderno) AS [Orders],  
        isnull(sum(isnull(oi.quantity,0)),0) as [Quantity], 
        isnull(oi.unitprice,0)AS [Unit Price], 
        isnull(sum(isnull(oi.extprice,0)),0)AS [Total Price] 
    from 
        orderupdates as ou  
        inner join orders o  on o.orderno = ou.orderno and o.orderno <> 'ZZZCUSTOM' 
        inner join orderdetails od  on od.orderno = o.orderno 
        inner join orderitems oi  on oi.orderno = o.orderno and oi.linenum = od.linenum 
        inner join items i  on i.itemid = od.itemid 
        inner join vendoritems vi  ON vi.ItemId=i.ItemId 
        left outer join VendorBuyers BORD  on BORD.Buyer = 'admin' and BORD.Usage = 10000 and BORD.VendorNo = O.VendorNo and BORD.fgSpecialPO = O.fgSpecialPO 
    where 
        case when BORD.EMailId is null then 
            case when IsNull(BORD.Type, 0) = 1 then 1 
            when O.fgSpecialPO in (0, 2, 4) then 1 
            when O.fgSpecialPO in (1, 3, 5) then 1 end 
            else 0 end = 1 
            and O.fgSpecialPO IN (0) 
            and ou.actdate >= '2015-05-01' 
            and ou.actdate < '2015-05-15' 
            and ou.type = 0 
    group by i.skuno, vi.skuno, i.description, oi.unitprice ) T
ORDER BY 
    TOT, [Quantity] DESC, [SKU No] 
0
Beau D'Amore 28 Дек 2015 в 17:45

2 ответа

Лучший ответ

Попробуйте вместо этого использовать GROUPING SETS. Это дает больше гибкости, чем ROLLUP

GROUP BY
    GROUPING SETS (
      (oi.unitprice, i.skuno, i.description),
      (i.skuno, vi.skuno, i.description, oi.unitprice)
    )

Потребуется несколько дополнительных настроек, например, несколько ISNULL(A,'') AS A и т. д. Купите, надеюсь, это поможет вам двигаться в правильном направлении.

См. https : //technet.microsoft.com/en-us/library/bb510427%28v=sql.105%29.aspx? f = 255 & amp; MSPPError = -2147217396 для получения дополнительных и некоторых примеров эквивалентности.

1
dsz 1 Янв 2016 в 08:57

Я бы сначала взглянул на подзапросы. Во внутреннем подзапросе верхней части объединения идет группа по i.description, но поле описания не используется в операторе выбора. Таблица элементов также упоминается в заявлении, но в ней нет необходимости.

SELECT 
    COUNT(distinct o.orderno) AS [Orders], 
    SUM(oi.quantity) as [Quantity], 
    oi.unitprice AS [Unit Price], 
    SUM(oi.extprice) AS [Total Price] 
FROM
    orderupdates ou  
INNER JOIN 
    orders o ON o.orderno = ou.orderno 
INNER JOIN 
    orderdetails od ON od.orderno = o.orderno 
INNER JOIN 
    orderitems oi ON oi.orderno = o.orderno 
                AND oi.linenum = od.linenum 
--INNER JOIN 
    --items i ON i.itemid = od.itemid 
WHERE
    actdate >= '2015-05-01' 
    AND ou.actdate < '2015-05-15' 
    AND type = 0 
GROUP BY
    oi.unitprice, i.skuno --, i.description

Есть больше оптимизаций, которые можно сделать с вашим оператором SQL.

0
Rick Gittins 4 Янв 2016 в 21:08