![](/img/trans.png)
[英]Best way to use Where Clause in SQL SERVER Query (for best performance)?
[英]Best way to rewrite a WHERE NOT IN clause?
我有一個類似下面的查詢:
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')
哪個更快但結果不匹配。 我這次重寫有什么問題嗎? 有一個更好的方法嗎?
也許這是一個錯字,但在第一個查詢中,您正在比較StuKey列,而在第二個查詢中,您正在加入Key
在性能方面,我希望2個查詢導致一個非常相似的(如果不是相同的)執行計划。 你應該檢查兩者的計划。
此外,請確保在運行之間清除數據緩存,因為它們實際上可以執行相同的操作,但由於緩存數據,第二個似乎更快。
我認為問題在於:
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'並將其重寫為列比較)
試試這個
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)
這將是效率和清晰度之間的良好平衡:
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或過程中,並使用子查詢的結果填充臨時表,使用主查詢中的該表,然后通過擦除進行清理臨時表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.