-2

我有这个查询需要 2 分钟才能执行,即使时间段不是那么长:

SELECT MTI.DeptID,
       ShortEmployees.EmpID,
       ShortEmployees.EmpName1 AS EmpName,
       Sum(CASE
             WHEN (BSR.BSTID = 3
                   AND bli.state IN (12, 13, 14)) THEN -1 * ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price - ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price * BLD.discount * 0.01))
             ELSE ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price - ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price * BLD.discount * 0.01))
           END) AS Total
FROM   BLD
       INNER JOIN BLI
         ON BLD.BLNo = BLI.BLNo
       INNER JOIN BSR
         ON BLI.BLID = BSR.BLID
       INNER JOIN ShortEmployees
         ON BLI.EmpID = ShortEmployees.EmpID
       INNER JOIN MTI
         ON BLD.MTID = MTI.MTID
WHERE  (MTI.DeptID = 'B')
       AND (BLI.BLDate > Cast('2013-01-01 00:00:00' AS DATETIME))
       AND (BLI.BLDate < Cast('2013-01-14 23:59:59' AS DATETIME))
       AND ((BSR.BSTID = 2
             AND bli.state IN (2, 6, 8, 9,
                               10, 12, 18))
             OR (BSR.BSTID = 3
                 AND bli.state IN (12, 13, 14)))
GROUP  BY ShortEmployees.EmpName1,
          ShortEmployees.EmpID,
          MTI.DeptID
ORDER  BY Total DESC

我该如何优化它?

MTI:项目信息表。

BLI:账单表。

BLD:账单明细表。

ShortEmployees:销售员表。

4

3 回答 3

1

将条件移动到 JOKN ON 子句中,在这些子句中可以在进行连接时应用它们,而不是在完成所有连接后进行过滤:

SELECT MTI.DeptID,
       ShortEmployees.EmpID,
       ShortEmployees.EmpName1 AS EmpName,
       Sum(CASE
             WHEN (BSR.BSTID = 3
                   AND bli.state IN (12, 13, 14)) THEN -1 * ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price - ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price * BLD.discount * 0.01))
             ELSE ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price - ((BLD.Qty / dbo.Getunitval(BLD.UnitID, BLD.MTID)) * BLD.Price * BLD.discount * 0.01))
           END) AS Total
FROM BLD
JOIN BLI ON BLD.BLNo = BLI.BLNo
    AND BLI.BLDate BETWEEN Cast('2013-01-01 00:00:00' AS DATETIME)
       AND Cast('2013-01-14 23:59:59' AS DATETIME)
JOIN BSR ON BLI.BLID = BSR.BLID
    AND ((BSR.BSTID = 2
             AND bli.state IN (2, 6, 8, 9, 10, 12, 18)
        OR (BSR.BSTID = 3
             AND bli.state IN (12, 13, 14))
JOIN ShortEmployees ON BLI.EmpID = ShortEmployees.EmpID
JOIN MTI ON BLD.MTID = MTI.MTID
    AND MTI.DeptID = 'B'
GROUP BY ShortEmployees.EmpName1,
    ShortEmployees.EmpID,
    MTI.DeptID
ORDER BY Total DESC

请注意,我将日期范围检查更改为 BETWEEN,因为您的查询排除了该期间的第一秒和最后几秒。

我还删除了不必要的括号和缩进

于 2013-01-14T09:36:32.990 回答
0

最后,我最终将该查询转换为整个存储过程,差异很大!现在只需要 2 秒 :),特别感谢大家讨厌的屁股 ;)

于 2013-01-17T05:52:59.043 回答
0

如需进一步优化,请将 Cast('XXXXX' AS DATETIME) 移动到变量中:

DECLARE @dmin DATETIME= Cast('2013-01-01 00:00:00' AS DATETIME);
DECLARE @dmax DATETIME= Cast('2013-01-14 23:59:59' AS DATETIME);
SELECT [blah]
FROM   [blahblah]
WHERE  (MTI.DeptID = 'B')
       AND (BLI.BLDate BETWEEN @dmin AND @dmax)
etc
于 2013-05-30T14:13:11.640 回答