SQL Server:UNION ALL两个语句与ROLLUP之间的存储过程性能

时间:2015-12-28 14:45:49

标签: sql sql-server tsql stored-procedures

我的任务是改进存储过程的性能,该存储过程使用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] 

2 个答案:

答案 0 :(得分:1)

请改用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&MSPPError=-2147217396

答案 1 :(得分:0)

我先看看子查询。在union的顶部的内部子查询中,通过i.description进行分组,但是select语句中没有使用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语句进行更多优化。