我有一个类似下面的查询:
Select ser.key
From dbo.Enrlmt ser
Where ser.wd >= @FromDate AND ser.wd <= @ThrouDate AND
ser.EnrlmtStatCode = '4321' AND
ser.StuExitCatgCode in ('1','2','3','4','5','6','7') AND
ser.Key not in (select Key
from Enrlmt ser2
where ser2.StartDate <= @AsOfDate
AND ser2.StartDate > ser.wd
AND ser2.EnrlmtStatCode = '4321')
由于“NOT IN”条款,这非常慢。我尝试使用左外连接重写它,使它看起来像:
Select ser.key
From dbo.Enrlmt ser
LEFT JOIN dbo.Enrlmt ser2 ON ser.key = ser2.key
AND ser2.StartDate <= @AsOfDate
AND ser2.StartDate > ser.wd
AND ser2.EnrlmtStatCode = '4321'
Where ser2.key is null
AND ser.wd >= @FromDate
AND ser.wd <= @ThrouDate
AND ser.EnrlmtStatCode = '4321'
AND ser.StuExitCatgCode in ('1','2','3','4','5','6','7')
哪个更快但结果不匹配。我这次重写有什么问题吗?有更好的方法吗?
答案 0 :(得分:2)
也许这是一个错字,但在第一个查询中,您正在比较 StuKey 列,而在第二个查询中,您正在加入键
在性能方面,我希望这两个查询会产生一个非常相似的(如果不是相同的)执行计划。你应该检查两者的计划。
另外,请确保在运行之间清除数据缓存,因为它们实际上可以执行相同的操作,但由于缓存数据,第二个似乎更快。
答案 1 :(得分:1)
我认为问题在于:
ser.StuKey not in (select StuKey
与:相比:
ON ser.key = ser2.key
所以重写应该是:
SELECT ser.key
FROM dbo.Enrlmt ser
LEFT JOIN Enrlmt ser2
ON ser.StuKey = ser2.Stukey
AND ser.EnrlmtStatCode = ser2.EnrlmtStatCode
AND ser2.StartDate > ser.wd
AND ser2.StartDate <= @AsOfDate
WHERE ser.wd >= @FromDate
AND ser.wd <= @ThrouDate
AND ser.EnrlmtStatCode = '4321'
AND ser.StuExitCatgCode in ('1','2','3','4','5','6','7')
AND ser2.key IS NULL
(注意我也删除了ser2.EnrlmtStatCode ='4321'并将其重写为列比较)
答案 2 :(得分:1)
试试这个
ser2.StartDate > ser.wd
,因为ser.wd >= @FromDate
?此外:
ser2.StartDate > ser.wd
,它们的数据类型是否相同?因此:
Select
ser.key
From
dbo.Enrlmt ser
Where
ser.wd >= @FromDate AND ser.wd <= @ThrouDate AND
ser.EnrlmtStatCode = '4321' AND
ser.StuExitCatgCode in ('1','2','3','4','5','6','7') AND
not EXISTS (select *
from Enrlmt ser2
where ser2.StartDate <= @AsOfDate
AND ser2.EnrlmtStatCode = '4321'
AND ser2.StartDate > @FromDate --ser.wd??
AND ser2.Key = ser.Key)
答案 3 :(得分:0)
这将是效率与清晰度之间的良好平衡:
Select ser.key
From
dbo.Enrlmt ser
Left Join (select StuKey
from Enrlmt
where Enrlmt.StartDate <= @AsOfDate AND
Enrlmt.EnrlmtStatCode = '4321') As ser2
ON ser.key = ser2.key And ser2.StartDate > ser.wd
Where
ser.wd >= @FromDate AND ser.wd <= @ThrouDate AND
ser.EnrlmtStatCode = '4321' AND
ser.StuExitCatgCode in ('1','2','3','4','5','6','7') AND
ser2.key Is Null
您可以通过将子查询设为UDF来提高速度。对于子查询执行大量工作的大量记录,请考虑将所有内容放在UDF或过程中,并使用子查询的结果填充临时表,在主查询中使用该表,然后通过擦除进行清理临时表。