Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server查询需要性能改进-使用groupby汇总在临时表上进行左联接_Sql Server_Sql Server 2008_Tsql_Group By_Left Join - Fatal编程技术网

Sql server SQL Server查询需要性能改进-使用groupby汇总在临时表上进行左联接

Sql server SQL Server查询需要性能改进-使用groupby汇总在临时表上进行左联接,sql-server,sql-server-2008,tsql,group-by,left-join,Sql Server,Sql Server 2008,Tsql,Group By,Left Join,我继承了一个巨大的查询/报表SP。它运行速度非常慢,扩展性不好。从它的书写方式来看,有很多左撇子的加入。它创建一个临时表,并将日期范围存储为datetime列中的各个日期,然后在此表上左键联接,以通过groupby/rollup从其他几个表获取信息,从而获取报告的总计。这是用我不熟悉的方式写的。我习惯于'WHERE'子句中的日期/参数,其中索引是一种优势 必须有更好的方法来做到这一点。也许只是一些明智的指导就好了。代码会更好。我一直在尝试通过CTE方法进行思考。有大量的ISNULL检查和嵌套转换

我继承了一个巨大的查询/报表SP。它运行速度非常慢,扩展性不好。从它的书写方式来看,有很多左撇子的加入。它创建一个临时表,并将日期范围存储为datetime列中的各个日期,然后在此表上左键联接,以通过groupby/rollup从其他几个表获取信息,从而获取报告的总计。这是用我不熟悉的方式写的。我习惯于'WHERE'子句中的日期/参数,其中索引是一种优势

必须有更好的方法来做到这一点。也许只是一些明智的指导就好了。代码会更好。我一直在尝试通过CTE方法进行思考。有大量的ISNULL检查和嵌套转换来节省时间,只留下一个日期供比较,非常草率

我是新来的,所以我还不能告诉你关于DB的更多信息,比如索引,等等,我听说在需要索引的地方没有索引,等等。这个系统是几年前建立的,在SQL Server 2008上。无论如何,问题是:

-- these are just sample dates as I have copied this from the SP into a query window since it's all dynamic sql and hard to read as just a red string.   
DECLARE @FromDate date = '2015-06-01'
DECLARE @ToDate date = '2015-06-02'
DECLARE @TempDate date
DECLARE @TempToDate date

-- from here down is the SP
CREATE TABLE #SSTempDates (TempDate DATETIME)

IF @FromDate = ''
    SET @TempDate = (SELECT CONVERT(NVARCHAR(10), MIN(ImportDate), 101) FROM OrdersViewWImport)
ELSE
    SET @TempDate = @FromDate

IF @ToDate = ''
    SET @TempToDate = (SELECT CONVERT(NVARCHAR(10),GETDATE(), 101))
ELSE
    SET @TempToDate = @ToDate

WHILE @TempDate < @TempToDate
BEGIN
    INSERT INTO #SSTempDates SELECT @TempDate
    SET @TempDate = DATEADD(D,1,@TempDate)
END

-- done creating the temp table that holds the dates to join on
SELECT CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 THEN 'Total' ELSE CONVERT(NVARCHAR(10), TD.TempDate, 101) END AS [Date], 
    SUM(ISNULL(SH.QtyShipped,0)) AS [Units Shipped], 
    SUM(ISNULL(SH.ShippedPrice,0)) AS [Pounds Shipped], 
    SUM(ISNULL(C.QtyCancel,0)) AS [Units Cancelled], 
    SUM(ISNULL(C.CancelledPrice,0)) AS [Pounds Cancelled], 
    SUM(ISNULL(PR.OrdersPrinted,0)) AS [Allocated Orders], 
    SUM(ISNULL(SH.OrdersShipped,0)) + SUM(ISNULL(A.OrdersAssigned,0)) AS [Shipped Orders], 
    SUM(ISNULL(PR.QtyPrinted,0)) AS [Items Allocated], 
    SUM(ISNULL(SH.QtyShipped,0)) + SUM(ISNULL(A.QtyAssigned,0)) AS [Items Shipped], 
    CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 THEN 
        CASE WHEN ISNULL(SUM(PR.QtyPrinted),0) = 0 THEN 0 
            WHEN CAST(CONVERT(DECIMAL,(ISNULL(SUM(SH.QtyShipped),0) + ISNULL(SUM(A.QtyAssigned),0))) / CONVERT(DECIMAL,ISNULL(SUM(PR.QtyPrinted),0)) * 100 AS DECIMAL(19,2)) > 100 THEN 100 
            ELSE CAST(CONVERT(DECIMAL,(ISNULL(SUM(SH.QtyShipped),0) + ISNULL(SUM(A.QtyAssigned),0))) / CONVERT(DECIMAL,ISNULL(SUM(PR.QtyPrinted),0)) * 100 AS DECIMAL(19,2)) END 
        ELSE SUM(CASE WHEN ISNULL(PR.QtyPrinted,0) = 0 THEN 0 
            WHEN CAST(CONVERT(DECIMAL,(ISNULL(SH.QtyShipped,0) + ISNULL(A.QtyAssigned,0))) / CONVERT(DECIMAL,ISNULL(PR.QtyPrinted,0)) * 100 AS DECIMAL(19,2)) > 100 THEN 100 
            ELSE CAST(CONVERT(DECIMAL,(ISNULL(SH.QtyShipped,0) + ISNULL(A.QtyAssigned,0))) / CONVERT(DECIMAL,ISNULL(PR.QtyPrinted,0)) * 100 AS DECIMAL(19,2)) END) END AS [Fill Rate %], 
    CAST(CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 THEN ISNULL(SUM(NP.[ID]) / ISNULL((SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])),0) * 100,0) 
        ELSE CASE WHEN SUM(NP.[ID]) = 0 THEN 0 
            ELSE ISNULL(SUM(NP.[ID]) / (SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])) * 100,0) END END AS DECIMAL(19,2)) AS [Inv Disc %], 
    CAST(CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 THEN ISNULL(SUM(NP.[NG]) / ISNULL((SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])),0) * 100,0) 
        ELSE CASE WHEN SUM(NP.[NG]) = 0 THEN 0 
            ELSE ISNULL(SUM(NP.[NG]) / (SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])) * 100,0) END END AS DECIMAL(19,2)) AS [NG %], 
    CAST(CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 THEN ISNULL(SUM(NP.[SS]) / ISNULL((SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])),0) * 100,0) 
        ELSE CASE WHEN SUM(NP.[SS]) = 0 THEN 0 
            ELSE ISNULL(SUM(NP.[SS]) / (SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])) * 100,0) END END AS DECIMAL(19,2)) AS [SS %],       
    CAST(CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 THEN ISNULL(SUM(NP.[ZO]) / ISNULL((SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])),0) * 100,0) 
        ELSE CASE WHEN SUM(NP.[ZO]) = 0 THEN 0 
            ELSE ISNULL(SUM(NP.[ZO]) / (SUM(NP.[ID])+SUM(NP.[NG])+SUM(NP.[ZO])+SUM(NP.[SS])) * 100,0) END END AS DECIMAL(19,2)) AS [ZO %], 
    CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 
        THEN CAST(AVG(CASE WHEN ISNULL(SH.AvgPrice,0) + ISNULL(A.AvgPrice,0) = 0 THEN 0 ELSE ISNULL(SH.AvgPrice,0) + ISNULL(A.AvgPrice,0) END) AS DECIMAL(19,2)) 
        ELSE CAST(SUM(ISNULL(SH.AvgPrice,0)) + SUM(ISNULL(A.AvgPrice,0)) AS DECIMAL(19,2)) END AS [AOV], 
    CASE WHEN GROUPING(CONVERT(NVARCHAR(10), TD.TempDate, 101)) = 1 
        THEN CAST(AVG(CASE WHEN ISNULL(SH.AvgQty,0) + ISNULL(A.AvgQty,0) = 0 THEN 0 ELSE ISNULL(SH.AvgQty,0) + ISNULL(A.AvgQty,0) END) AS DECIMAL(19,2)) 
        ELSE SUM(ISNULL(SH.AvgQty,0)) + SUM(ISNULL(A.AvgQty,0)) END AS [UPO] 

    FROM (SELECT DISTINCT TempDate FROM #SSTempDates) TD 
    LEFT JOIN ( 
        SELECT COUNT(DISTINCT OrderNo) AS OrdersPrinted, SUM(Quantity) AS QtyPrinted, CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101)) AS PrintBatchDate 
        FROM PickTicketsOrders WITH (NOLOCK) 
        GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101))) PR ON PR.PrintBatchDate=CONVERT(NVARCHAR(10), TD.TempDate, 101) 
    LEFT JOIN ( 
        SELECT COUNT(DISTINCT OI.OrderNo) AS OrdersShipped, SUM(OI.Quantity) AS [QtyShipped], SUM(OI.ExtPrice) AS ShippedPrice, CONVERT(DATETIME,CONVERT(NVARCHAR, S.ShipBatch, 101)) AS ShipDate, 
            CAST(AVG(OI.ExtPrice) AS DECIMAL(19,6)) AS AvgPrice, CAST(AVG(OI.Quantity) AS DECIMAL(19,6)) AS AvgQty 
        FROM Shipments S WITH (NOLOCK) 
        inner join (SELECT OrderNo, GroupNum, SUM(Quantity) AS Quantity, SUM(ExtPrice) AS ExtPrice FROM OrderItems GROUP BY OrderNo, GroupNum) OI  ON OI.OrderNo = S.OrderNo AND OI.GroupNum = S.GroupNum 
        GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, S.ShipBatch, 101))) SH ON SH.ShipDate=CONVERT(NVARCHAR(10), TD.TempDate, 101) 
    LEFT JOIN ( 
        SELECT COUNT(DISTINCT OI.OrderNo) AS OrdersAssigned, SUM(OI.Quantity) AS [QtyAssigned], CONVERT(DATETIME,CONVERT(NVARCHAR, OA.ActDate, 101)) AS ActDate, 
            CAST(AVG(OI.ExtPrice) AS DECIMAL(19,6)) AS AvgPrice, CAST(AVG(OI.Quantity) AS DECIMAL(19,6)) AS AvgQty 
        FROM OrderActions OA WITH (NOLOCK) 
        INNER JOIN PndShipments P WITH (NOLOCK) ON P.OrderNo=OA.OrderNo AND P.GroupNum=OA.grouplinenum 
        INNER JOIN OrderItems OI WITH (NOLOCK) ON OI.OrderNo=P.OrderNo AND OI.GroupNum=P.GroupNum 
        INNER JOIN Orders O WITH (NOLOCK) ON O.OrderNo=OA.OrderNo 
        WHERE OA.Type=31 
        GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, OA.ActDate, 101))) A ON A.ActDate=CONVERT(NVARCHAR(10), TD.TempDate, 101) 
    LEFT JOIN ( 
        SELECT SUM(OI.Quantity) AS QtyCancel, SUM(OI.ExtPrice) AS CancelledPrice, CONVERT(DATETIME,CONVERT(NVARCHAR, CC.CancelDate, 101)) AS CancelDate 
        FROM OrderItems OI WITH (NOLOCK) 
        INNER JOIN Cancels CC WITH (NOLOCK) ON CC.OrderNo=OI.OrderNo AND CC.GroupNum=OI.GroupNum 
        GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, CC.CancelDate, 101))) C ON C.CancelDate=CONVERT(NVARCHAR(10), TD.TempDate, 101) 
    LEFT JOIN ( 
        SELECT CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101)) AS TotalNonPickDate, 
            SUM(CASE WHEN NoPickReason Like 'ID%' THEN 1.0 ELSE 0.0 END) AS [ID], 
            SUM(CASE WHEN NoPickReason Like 'NG%' THEN 1.0 ELSE 0.0 END) AS [NG], 
            SUM(CASE WHEN NoPickReason Like 'SS%' THEN 1.0 ELSE 0.0 END) AS [SS], 
            SUM(CASE WHEN NoPickReason Like 'ZO%' THEN 1.0 ELSE 0.0 END) AS [ZO] 
            FROM PickTickets WITH (NOLOCK) 
            WHERE PickBatch<>PrintBatch AND NoPickReason IN ('NG*','NG','ID*','ID','SS*','SS','ZO*','ZO') 
            GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101))) NP ON NP.TotalNonPickDate=CONVERT(NVARCHAR(10), TD.TempDate, 101)

    WHERE (ISNULL(C.QtyCancel,0) > 0 OR ISNULL(PR.QtyPrinted,0) > 0 OR ISNULL(SH.QtyShipped,0) + ISNULL(A.QtyAssigned,0) > 0 OR 
        ISNULL(NP.[ID],0) > 0 OR ISNULL(NP.[NG],0) > 0 OR ISNULL(NP.[SS],0) > 0 OR ISNULL(NP.[ZO],0) > 0 ) 

    GROUP BY CONVERT(NVARCHAR(10), TD.TempDate, 101) WITH ROLLUP ORDER BY [Date]

drop table #SSTempDates

首先,检查索引。 那么在以下情况下有太多的操作:

on, where
从中删除任何操作,如CONVERT、ISNULL、+等

让我们先看看加入

    LEFT JOIN ( 
    SELECT COUNT(DISTINCT OrderNo) AS OrdersPrinted, SUM(Quantity) AS QtyPrinted, CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101)) AS PrintBatchDate 
    FROM PickTicketsOrders WITH (NOLOCK) 
    GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101))) PR ON PR.PrintBatchDate=CONVERT(NVARCHAR(10), TD.TempDate, 101) 
最好是写信

LEFT JOIN ( 
    SELECT COUNT(DISTINCT OrderNo) AS OrdersPrinted, SUM(Quantity) AS QtyPrinted, CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101)) AS PrintBatchDate 
    , PrintBatch 
    FROM PickTicketsOrders WITH (NOLOCK) 
    GROUP BY CONVERT(DATETIME,CONVERT(NVARCHAR, PrintBatch, 101))) PR ON PR.PrintBatch=TD.TempDate
您的每个join都使用CONVERT。像我上面写的那样重写它

第二。看哪 每一个 ISNULLC.QtyCancel,0>0 会更好 C.QtyCancel>0

因为如果C.QtyCancel为null,那么C.QtyCancel>0也是false默认服务器设置,所以我们得到了相同的结果。 但函数ISNULL可能会破坏执行计划

另一件坏事在哪里 ISNULLSH.QtyShipped,0+ISNULLA.qtyAsigned,0>0

写起来很短,但会减慢查询速度


您的SQL太复杂了,您可能希望在没有任何示例数据的情况下在线处理它,也不清楚其用途。所有这些聚合和连接都足够可怕,但谁知道它们也可能是完全正确的。我也会想到CTE,而且这段代码看起来像是在尖叫交叉应用。是的,我没有发布任何数据,但谢谢。把每个派生表都放一个临时表,在每个临时表中都有一个日期。为什么需要在SELECT distinct TempDate中使用distinct?正如我前面所说,我继承了这一点,distinct是因为某些天没有数据,所以它不是在报告中有一个空行,而是从OrdersViewImport中选择可能没有连续日期的日期。有些日期可能不存在,有些日期有多行,因此DISTINCTwait,我的错,这只是循环将日期插入临时表中。。这真是浪费,谢谢你指出这一点谢谢你的输入,但正如我前面所述,CONVERT命令用于从datetime中删除时间,否则2015-01-01将类似于2015-01-01 11:25:24,并且日期比较将不起作用,因此我无法删除它们。我可以用DATEADDdd,DATEDIFFdd,0,xxxx,0来代替它们,但在测试中性能更差。是的,但这不是一个好方法。SQL server 2008是否具有日期数据类型?迄今为止的铸造应该更好。或者,在最坏的情况下,转换为yyyymmdd ISO格式,在这种情况下,执行DateDiff是首选方法。演员的想法我已经尝试过了,但是没有成功。此查询需要重写。我试图找到一个能从不同角度看到这一点的人,把大的查询变成几个小的查询。每个左撇子都加入。并对其进行评估。设置@DT=getdate;子查询打印日期diffms,@DT,getdate;