2013-03-11 193 views
21

我在一個非常大的表中有一個SQL datetime字段。它被索引並需要被查詢。在Microsoft SQL Server中比較日期的最佳方法是什麼?

問題是,SQL總是存儲時間組件(儘管它總是午夜),但搜索是到了一天,而不是時間。

declare @dateVar datetime = '2013-03-11; 

select t.[DateColumn] 
from MyTable t 
where t.[DateColumn] = dateVar; 

不會返回任何東西,因爲t.[DateColumn]總是包含時間分量。

我的問題是什麼是最好的方法呢?

似乎有要的選項兩個主要的組:

  1. 創建使用dateadd第二可變,並使用一個或between ... and>= ... and ... <=

  2. t.[DateColumn]轉換爲僅限日期的組件 - 我認爲這會導致任何索引被忽略。

這兩種看起來都很混亂 - 我並不真想進行範圍比較或掃描表格。

有沒有更好的方法?

如果其中一個選項始終是最佳方式,那麼如何以及爲什麼?

回答

24

轉換爲DATE或在任何情況下使用開放式日期範圍將產生最佳性能。僅供參考,使用指數轉換爲日期是表現最好的。那篇文章

DECLARE @dateVar datetime = '19700204'; 

-- Quickest when there is an index on t.[DateColumn], 
-- because CONVERT can still use the index. 
SELECT t.[DateColumn] 
FROM MyTable t 
WHERE = CONVERT(DATE, t.[DateColumn]) = CONVERT(DATE, @dateVar); 

-- Quicker when there is no index on t.[DateColumn] 
DECLARE @dateEnd datetime = DATEADD(DAY, 1, @dateVar); 
SELECT t.[DateColumn] 
FROM MyTable t 
WHERE t.[DateColumn] >= @dateVar AND 
     t.[DateColumn] < @dateEnd; 

另外:在文章測試不同的技術:發佈What is the most efficient way to trim time from datetime?亞倫伯特蘭

那篇文章使用BETWEENDATEDIFFCONVERT(CHAR(8)...都慢。

+2

@凱斯感謝您指定的例子..和很好的問題;) – 2013-03-12 12:59:03

10

下面是一個例子:

我有一個訂單表叫做訂購日期日期時間字段。我想檢索訂單日期等於01/01/2006的所有訂單。旁邊還有如何做到這一點:

1) WHERE DateDiff(dd, OrderDate, '01/01/2006') = 0 
2) WHERE Convert(varchar(20), OrderDate, 101) = '01/01/2006' 
3) WHERE Year(OrderDate) = 2006 AND Month(OrderDate) = 1 and Day(OrderDate)=1 
4) WHERE OrderDate LIKE '01/01/2006%' 
5) WHERE OrderDate >= '01/01/2006' AND OrderDate < '01/02/2006' 

是發現here

+0

,# 1被認爲是最有效的:http://www.sqlservercentral.com/Forums/Topic937765-338-1.aspx – RandomUs1r 2013-03-11 17:33:18

+1

@ RandomUs1r選項#1需要對錶中的每一行運行'datediff'計算,它肯定會贏得不是最快或最有效的。與#varchar(20)'轉換相同的選項#2。選項#4和#5更有希望,我會再添加兩個:6)'其中@dateVar和dateadd(day,1,@dateVar)'和7)'WHERE convert(date,OrderDate)= @ dateVar' – Keith 2013-03-12 09:41:42

+3

這5個建議的方法1-4都很慢。 5對於堆表很快,最快的方法('convert(date,OrderDate)'見所選答案)甚至不在列表中。 – Keith 2013-03-12 12:08:54

0

你可以添加一個計算列僅包括沒有時間的日期。在這兩個選項之間,我會選擇BETWEEN運算符,因爲它對我來說更「乾淨」,應該更好地使用索引。比較執行計劃似乎表明BETWEEN會更快;然而,在實際測試中他們表現相同。

+1

事實證明[''這裏''是一個壞主意](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between-and-the-devil-have-在-common.aspx)。 – Keith 2013-03-12 12:04:52

+1

@Keith +1感謝您的鏈接。我知道大部分問題(我知道它是包容性的,我習慣性地在需要時爲結束日期添加一個時間值),但最後幾個對我來說是新的。在工作中,我們選擇的所有時間值都被截斷爲分鐘或秒鐘(不,那不是我的決定,是的,精度的缺乏令人討厭),所以納秒問題還沒有出現,但它們可能已經足夠嚴重了,我可能會提出將'BETWEEN'改爲'=> ... <'以便今天與其他開發者討論。 – 2013-03-12 12:26:52

0

當日期介於fromdate和toDate之間時,獲取項目。

其中 轉換(日期,沒有fromdate,103)< = '2016年7月26日',並轉換(日期,TODATE,103)> = '2016年7月26日' 所有這些的

+2

嗨@gaze,歡迎來到堆棧溢出。你的答案在這裏沒有真正添加任何東西 - 如果你閱讀接受的答案,你會看到他們已經覆蓋了'convert'並解釋了改變類型還是使用更好基於索引,這實際上是我問的對於。爲了獲得最多的票數,你真的需要添加其他人沒有的東西,或者先回答。 – Keith 2016-07-26 06:57:58

相關問題