是否有任何方法可以优化此SQL Server查询?

是否有任何方法可以优化此SQL Server查询?,sql,sql-server,Sql,Sql Server,我有一个需要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.Getun

我有一个需要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.DeptID,
ShortEmployees.EmpID,
ShortEmployees.EmpName1作为EmpName,
总数(例)
当(BSR.BSTID=3
然后-1*((BLD.Qty/dbo.Getunitval(BLD.UnitID,BLD.MTID))*BLD.Price-((BLD.Qty/dbo.Getunitval(BLD.UnitID,BLD.MTID))*BLD.Price*BLD.折扣*0.01))
其他((BLD.Qty/dbo.Getunitval(BLD.UnitID,BLD.MTID))*BLD.Price-((BLD.Qty/dbo.Getunitval(BLD.UnitID,BLD.MTID))*BLD.Price*BLD.折扣*0.01))
(完)总计
来自BLD
内连接BLI
ON BLD.BLNo=BLI.BLNo
内连接BSR
ON BLI.BLID=BSR.BLID
内部员工
在BLI.EmpID=ShortEmployees.EmpID上
内连接MTI
在BLD.MTID=MTI.MTID上
其中(MTI.DeptID='B')
和(BLI.BLDate>Cast('2013-01-01 00:00:00'为日期时间))
和(BLI.BLDate
我如何优化它

MTI:项目信息表

比尔表

BLD:账单明细表


ShortEmployees:Salesmen表。

将条件移动到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
请注意,我将日期范围检查更改为介于之间,因为您的查询排除了时段的第一秒和最后一秒


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

最后,我将该查询转换为整个存储过程,差别是巨大的!现在只需要2秒钟:),谢谢大家,特别是仇恨者斯潘基;)

要进行其他优化,请在变量中移动强制转换('XXXXX'作为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

第一步是将查询分成格式更好的行,这样人们甚至可以开始尝试优化它这些表上有哪些索引?是的,可以优化
dbo.Getunitval
;)@Mhdali他是对的,如果你不付出最小的努力,大多数人会继续前进。下一次,尝试通过我使用的在线格式化程序运行您的查询:我同意@TimSchmelter-从名称来看,它听起来像是一个可以转换为联接的函数。以前需要1:53,现在需要1:55:D没有太大区别。