2012-08-14 138 views
4

我想知道什麼是針對具有日期(無時間)的記錄集的日期時間查詢的「最佳實踐」方法。MSSQL針對一天或一天​​範圍的日期範圍的最佳查詢

我使用了幾個查詢,它們使用日期時間數據類型從記錄集中返回基於日期範圍的記錄,這意味着每個記錄都需要使用範圍進行檢查。

查詢的例子是:

Select * 
FROM Usages 
where CreationDateTime between '1/1/2012' AND '1/2/2012 11:59:59' 

我知道用BETWEEN是耗資源,並在檢查的日期的日期時間數據類型總是會非常資源緊張,但我想聽到別人在這種情況下使用(或將使用)的內容。

我會得到的日期時間記錄轉換爲像一個日期的任何類型的性能提升:

Select * 
FROM Usages 
where CONVERT(DATE,CreationDateTime) between '1/1/2012' AND '1/2/2012' 

,或者執行的再/再少更大的支票?

Select * 
FROM Usages 
where (CreationDateTime > '1/1/2012') 
    AND (CreationDateTime < '1/2/2012 11:59:59') 

回答

6

你以爲你知道的是不正確的。

既不使用BETWEEN或DATETIME數據類型是資源豬。

假設您對列進行索引,該列確實是DATETIME而不是VARCHAR(),並且您不會將該字段包裝在函數中,那麼所有內容都將很好且快捷。

也就是說,我會用>=<來代替。不是爲了表現,而是在邏輯上的正確性。

WHERE 
    myField >= '20120101' 
    AND myField < '20120102' 

無論該字段是包含小時,分鐘還是甚至(具有神話數據類型)微微秒,這都可以工作。

使用該字段上的索引,它也將提供範圍掃描。

你不會得到更快。不需要任何技巧或功能。

+0

感謝您的反饋,我沒有意識到使用20120201而不是02/01/2012以這種方式工作,並感謝確認處理這些類型查詢的最佳方法。 – Eric 2012-08-14 19:20:48

+3

@eric - 20120201T00:00:00.000''的好處是它不依賴於語言*(它總是被解釋爲日期部分的'YYYYMMDD')*。 「02/01/2012」可以是2月1日或2月1日,取決於你來自哪裏。 – MatBailie 2012-08-15 07:28:57

0

關於日期有幾個注意事項。

首先,您要確保相關索引得到使用。一般來說,這意味着避免列上的功能。這適用於除日期以外的數據類型,但功能普遍用於理解日期。所以,從性能的角度來看,CONVERT()是一個壞主意,假設該列是索引的。

其次,你想避免格式之間不必要的轉換。所以,對每一行都必須調用函數。相反,在編譯時將一個常量字符串轉換爲日期/時間。第一個效率較低。避免CONVERT()的另一個原因。但是,在許多查詢中,其他處理(如連接)比轉換耗時更多,因此這可能並不重要。

至於「之間」和簽名操作之間的選擇。更好的做法是使用「<」和「>」和「> =」和「< =」。它使日期的邏輯更加清晰,並且不像秒精確到3毫秒這樣的問題。

據我所知,在日期之間作爲有效使用索引作爲其他類型的字段。但是,爲了準確性和便攜性,最好進行單獨的比較。

因此,第三版將是優選的。

+1

對於連續變量(而不是離散變量),它應該是'> = AND <'而不是'> AND <'。此外,使用函數*(包括'CONVERT()')*的考慮不是操作的代價,而是它混淆了索引 - 因此在每一行都單獨處理,而不是用於快速生成範圍掃描。 – MatBailie 2012-08-14 18:06:10

+0

感謝球員的反饋。除非需要,我通常會嘗試不使用函數(通常在提取後處理轉換數據)。哦,是的,我使用> =和<=與查詢,我只是忘記包括euqals在試圖讓我的帖子/例子儘可能小。 – Eric 2012-08-14 19:24:21