【问题标题】:sql stored procedure - i would like to change it to a job but it has parameterssql 存储过程 - 我想将其更改为作业,但它有参数
【发布时间】:2016-08-13 06:20:07
【问题描述】:

我有一个运行时间很长、很繁重的存储过程,所以我想把它改成每晚运行并更新表的作业,以便用户可以在白天快速运行它。我的问题是它在左连接中接受参数,所以我不知道我该怎么做。我试图从连接中删除参数并只获取所有记录,但第一个问题是这些左连接是使用 group by 子句连接到表值函数(所以现在有大量记录)以及当我这样做的时候,它使我的整个服务器崩溃了。我将发布我存储过程的一部分,让您了解我现在正在做什么。

--或者,我会选择一个可以将我的查询性能从 2 分钟更改为 10 秒的答案。 :)

--顺便说一句,另一个导致查询速度变慢的原因是函数正在查询链接服务器...

create PROC [dbo].[mySP]
        @FromDate DateTime,
        @ToDate DateTime = NULL,
        @Style NVARCHAR(max),
        @ItemType  NVARCHAR(300),
        @ItemCode NVARCHAR(150)= null,
        @ItemsNotSold INT,
        @MultiplyUsage DECIMAL(18,4),
        @SParts BIT, 
        @vendorId nvarchar(50),
        @currentPage int, 
        @largeOrderSoNumbers nvarchar(300) = null,
        @excludeprojTag BIT,
        @hasOrderQty BIT = null,
        @createPO BIT = null,
        @excludeTestOrders BIT = null,
        @refresh BIT = null,
        @userid int = null,
        @positiveOverUse BIT = null
AS


SELECT @FROMDATE = @FROMDATE
,@ToDate=@ToDate
,@Style=@Style
,@ItemType=@ItemType
,@ItemCode=@ItemCode
,@ItemsNotSold=@ItemsNotSold
,@MultiplyUsage=@MultiplyUsage
,@SParts=@SParts
,@vendorId=@vendorId
,@currentPage=@currentPage
,@largeOrderSoNumbers=@largeOrderSoNumbers
,@excludeprojTag=@excludeprojTag
,@hasOrderQty =@hasOrderQty
,@createPO =@createPO
,@excludeTestOrders =@excludeTestOrders
,@refresh =@refresh
,@userid =@userid
,@positiveOverUse=@positiveOverUse

DECLARE @amountPerPage int = 400;
DECLARE @startingPoint int = (@currentpage - 1) * @amountPerPage 

SET @TODATE = NULLIF(@TODATE,'1/1/4000');
SET @ITEMCODE = NULLIF(@ITEMCODE,'');
SET @largeOrderSoNumbers = NULLIF(@LARGEORDERSONUMBERS,'');


BEGIN
    IF @Style = '-1'
        SET @Style = NULL
    IF @ItemType = '-1'
        SET @ItemType = NULL
END




SELECT
    ISNULL(c.NewQB_ListID,iit.ListID) ListID,   
    (select salesdesc from iteminventory i where i.listid = ISNULL(c.NewQB_ListID,iit.ListID)) as SalesDesc,
    isnull(inl.linename,'') + isnull(c.NewName,Name)    as ItemCode ,
    max(il.CubicMeterKD) as CubicMeterKD,

    sum(CONVERT(decimal(18,4),inl.Quantity) )
    - sum(CONVERT(decimal(18,4),inl.qtyRuleTag))
+ CONVERT(decimal(18,4),isnull(ai.qty,0))
 -CONVERT(decimal(18,4),isnull(ai.QtyRuleTag,0))   
  AS TotalQtyUesd,  
    sum(convert(decimal(18,4),isnull(inl.QtyRuleTag,0))) 
     as QtyUsedWithProjectTag,
    Convert(decimal(18,4),QuantityOnHand) as OnHand,
    CONVERT(int,ISNULL(EzQtyOnSO.Qty,0)) as OnSalesOrder,
    CONVERT(int,ISNULL(EzQtyAnyStatus.QtyLgO,0))as OnLgOrder,
    Convert(decimal(18,4),QuantityOnOrder) as OnPO,
    Convert(decimal(18,4),isnull(LargePO.lgOrderQtyOnPO,0)) as lgOrderQtyOnPO ,
    fl.LineName
    INTO #Q
FROM 
    iteminventory iit 

LEFT JOIN Lines fl
        ON iit.ParentRef_ListID = QB_LisiID 

LEFT JOIN tb_ItemList il
        ON iit.ListID = il.QBListID 


LEFT JOIN InlSales(@FromDate,@ToDate, @excludeprojtag, @excludeTestOrders) INL 
        ON IIT.LISTID = INL.ITEMREF_LISTID  


LEFT JOIN tb_CombinedItems c
        ON iit.ListID = c.ListID 

LEFT JOIN [QuantityInvoice](@FromDate, @ToDate,@excludeprojTag,@excludeTestOrders) as ai 
        ON ai.QBID = iit.ListID 

LEFT JOIN   fn_QuantityOnSalesOrder(@excludeTestOrders) AS EzQtyOnSO 
        ON iit.ListID = EzQtyOnSO.QBID

LEFT JOIN QuantityAnyStatus(@largeOrderSoNumbers, @excludeprojTag) AS EzQtyAnyStatus 
        ON iit.ListID = EzQtyAnyStatus.QBID

LEFT JOIN dbo.[FN_LargePO](@excludeTestOrders) LargePO --WITH (nolock) 
        ON LargePO.QBID = iit.ListID

WHERE 
    (@Style is null or ISNULL(c.ParentListID,ParentRef_ListID) in (SELECT Value From fn_MultiValueParameter(@Style))) AND
    (@ItemType is null or ItemTypeCode in (SELECT Value From fn_MultiValueParameter(@ItemType))) AND
    (@ItemCode is null or il.ItemCode like '%' + @ItemCode + '%') AND
    (IsActive = 1 OR c.ListID IS NOT NULL)

GROUP BY 
    ISNULL(c.NewQB_ListID,iit.ListID),
    ISNULL(c.NewName,Name),
    inl.LineName,
    QuantityOnHand,
    iit.QuantityOnOrder,
    CONVERT(int,ISNULL(EzQtyOnSO.Qty,0)),
    fl.LineName,
    CONVERT(decimal(18,4),isnull(ai.qty,0)),
    Convert(decimal(18,4),isnull(LargePO.lgOrderQtyOnPO,0)),
    CONVERT(int,ISNULL(EzQtyAnyStatus.QtyLgO,0)),
CONVERT(decimal(18,4),isnull(ai.QtyRuleTag,0))



IF @ItemsNotSold = 1
    BEGIN 
        DELETE FROM #Q
        WHERE isnull(TotalQtyUesd,0) <> 0 
    END
IF @ItemsNotSold = 2
    BEGIN 
        DELETE FROM #Q
        WHERE isnull(TotalQtyUesd,0) = 0
    END 



    SELECT 
        q.ListID,
        q.SalesDesc,
        q.ItemCode,
        MAX(isnull(q.CubicMeterKD,0)) as CubicMeterKD,
        SUM(q.TotalQtyUesd)
         TotalQtyUesd,
        SUM(q.QtyUsedWithProjectTag) as QtyUsedWithProjectTag,
        SUM(q.OnHand)  OnHand,
        SUM(q.OnSalesOrder) OnSalesOrder,
        SUM(q.OnLgOrder) OnLgOrder,
        SUM(q.OnPO) 
        - isnull(SUM(q.lgOrderQtyOnPO),0)  
        OnPO,
        SUM(q.lgOrderQtyOnPO) as lgOrderQtyOnPO,
        LineName
        INTO #QTY  
    FROM 
        #Q q 

    GROUP BY 
        q.ListID,
        q.salesdesc,
        q.ItemCode,
        q.LineName

        ;WITH Results AS
(
        SELECT 
            isnull(P.listid,'') as ListID,
            isnull(P.SalesDesc,'') as SalesDesc,
            isnull(P.itemcode,'')  as ItemCode,
            ISNULL(CubicMeterKD,0) AS CubicMeterKD,
            isnull(TotalQtyUesd,0)  as TotalQtyUsed,
            isnull(QtyUsedWithProjectTag,0) as QtyUsedWithProjectTag,
            isnull(onhand,0) as OnHand,
            isnull((OnHand - OnSalesOrder - OnLgOrder),0) as available, 
            isnull(OnLgOrder,0) as OnLgOrder,       
            isnull(OnPO,0) as OnPo,
            isnull(lgOrderQtyOnPO,0) as lgOrderQtyOnPO, 
            isnull(((OnHand - OnSalesOrder) + OnPO) ,0) AS [AvailableAndOnPo],
            isnull((TotalQtyUesd  * @MultiplyUsage) - ((OnHand - OnSalesOrder) + OnPO),0) AS [AvlOnPOminusUsed],
            isnull((((TotalQtyUesd * @MultiplyUsage) - ((OnHand - OnSalesOrder) + OnPO)) / CASE WHEN TotalQtyUesd > 0 THEN TotalQtyUesd END)*100,0) AS PctOver
            ,isnull(linename,0) as LineName,
            isnull((select price from qbdb.dbo.tb_iteminfodetail where vendorlistid = @vendorid and itemcode =isnull(P.itemcode,'')),0.0) as price
            ,isnull(pod.qtytoReOrder,0) as qtyToReOrder
            ,isnull(pod.qtytoOrder,0) as qtyToOrder
            ,isnull(pod.includePO,0) as includePO
            ,ROW_NUMBER() OVER (ORDER BY ITEMCODE) AS RowNum

        FROM  #qty AS p
        left join dbo.purchaseorderpreliminarydetails pod on pod.listid = P.listid and pod.deleteFlag = 0
        and headerid = (select top 1 headerid from purchaseorderpreliminary where deleteFlag = 0)
        WHERE 

        CASE WHEN @positiveOverUse = 1 THEN 
        isnull((((TotalQtyUesd * @MultiplyUsage) - ((OnHand - OnSalesOrder) + OnPO)) / CASE WHEN TotalQtyUesd > 0 THEN TotalQtyUesd END)*100,0) 
        ELSE 1 END >0

        AND
        case when  @hasOrderQty = 1 then isnull(pod.QtyToReOrder,0) else 1 end > 0 
        and 

        CASE WHEN @SPARTS = 1 THEN CASE WHEN 
        ItemCode IN (
                        'APP',
                        'CD',
                        '-S',
                        'L0',
                        'L/42',
                        'L01',
                        'Lfrgs2',
                        'Lfad2',
                        'Sfasdf9',
                        'SdafdsA',
                        'Sfasdf3',
                        'Sasdf6',
                        'asdf0',
                        'Sf6',
                        'fasdfadf2',
                        'fasdfasdf',
                        'S2236',
                        'S12342',
                        'Sdf 30',
                        'SdfE 36',
                        'fgsfgs',
                        'fasdf-fdasf',
                        'fadf',
                        'fasdf-fasdf',
                        'sdaf',
                        'adf 11"',
                        'fda 14"',
                        'fdas 24"') THEN 1 ELSE 0 END ELSE 1 END = 1
    )
    SELECT (select count(rownum) from results) as totalItems,* FROM Results WHERE 
    rownum between @startingPoint + 1 and @startingPoint + @amountPerPage

【问题讨论】:

  • 标记使用的 dbms。 (该代码与 ANSI SQL 相差甚远。)
  • 我不明白,你能不能不只是从作业中调用存储过程以便安排它?
  • 不,它有依赖于用户输入的参数。

标签: sql-server performance tsql query-optimization


【解决方案1】:

有一个表格,用户可以在他们回家之前将他们的参数输入,并将它们保存到数据库中的一个新表中。更改存储过程以从该新表中获取参数或在连接 &c 中使用新表。 SP 现在不需要将参数发送给它。最后通过 Job 调用 SP。

【讨论】:

  • 不,那行不通。他们可以每天多次更改参数。
  • 当他们这样做时会发生什么?如果有几组参数,您是否计划在同一天多次调用该作业?还是隔夜几次?或者为每组参数创建一个新作业?当你问这个问题时,你一定有什么计划......
  • 不,我唯一的计划是将所有数据收集到一个没有连接和计算的表中,然后允许用户将参数放入其中。
  • 这个SP在做什么?它是返回数据,还是更新/插入/删除或两者兼而有之?
  • 您是否尝试过在 SSMS 中运行查询(用代表值替换参数)并查看查询计划?
猜你喜欢
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多