2010-01-04 107 views
8

如何僅比較SQL Server 2005中DateTime數據類型的時間部分?例如,我想在特定時間後獲取MyDateField所在的所有記錄。下面的例子是一個很長的,也許不是快速的方法。 我想所有的日期,其中MyDateField大於12:30:50.400比較SQL Server 2005中DateTime數據類型的時間部分

SELECT * 
FROM Table1 
WHERE  ((DATEPART(hour, MyDateField) = 12) AND (DATEPART(minute, MyDateField) = 30) AND (DATEPART(second, MyDateField) = 50) AND (DATEPART(millisecond, MyDateField) > 400)) 
     OR ((DATEPART(hour, MyDateField) = 12) AND (DATEPART(minute, MyDateField) = 30) AND (DATEPART(second, MyDateField) > 50)) 
     OR ((DATEPART(hour, MyDateField) = 12) AND (DATEPART(minute, MyDateField) > 30)) 
     OR ((DATEPART(hour, MyDateField) > 12)) 
+0

請注意,如果您確實需要分別處理日期和時間,則會有效地破壞規範化規則。日期時間值是日期的特定時間點。日期和時間是一個多值字段,應該被分解。你的代碼運行緩慢的原因是你沒有正確地標準化它。 – 2010-01-04 18:26:31

+0

@Lasse - 你會用多久?毫無疑問,您不會將日期存儲在不同的字段中:日,月,年,小時,分鐘,工作日,週末,季度,星期。 – JeffO 2010-01-04 18:46:23

+0

@Lasse - 當然,我可以在日期和時間字段中分隔DateTime字段。但是,然後我會有同樣的問題來比較日期和時間在一起。 – 2010-01-04 19:04:45

回答

10
SELECT * 
FROM Table1 
WHERE DATEADD(day, -DATEDIFF(day, 0, MyDateField), MyDateField) > '12:30:50.400' 
+0

我認爲這是迄今爲止最好的解決方案。這很清楚,也很容易理解。它也是關於只有查詢而不是數據庫結構的最快解決方案。 – 2010-01-05 13:33:00

5

這個怎麼樣?

SELECT (fields) 
FROM dbo.YourTable 
WHERE DATEPART(HOUR, MyDate) >= 12 
    AND DATEPART(MINUTE, MyDate) >= 23 
    AND DATEPART(SECOND, MyDate) >= 45 

小時以24小時格式給出,例如, 12意味着中午12點,15意味着下午3點。

DATEPART對分,秒等也有「部分」。只要你喜歡,你當然可以在WHERE子句中使用盡可能多的日期部分。

+0

如果中午是截止時間,那麼邏輯可能應該是'hour> = 12'或者可能是'hour> 12或(hour = 12 and millisecond> 0)'。 – LukeH 2010-01-04 17:27:19

+0

@Luke:好點,是的 - 我打算使用> = .... – 2010-01-04 17:30:05

+0

但我也想考慮時間部分的其他部分,不僅是小時。 – 2010-01-04 17:46:44

-1

轉換(VARCHAR(10),指明MyDate,108)

這給你格式HH的時間字符串:MM:SS。

那麼你可以做你想做的事情

+0

時間部分還包含毫秒...還有一個格式還返回全部時間部分?我正在尋找的是一種排除日期部分只留下時間的方法。 – 2010-01-04 17:50:38

1

我想做任何比較的提取日期時間數據類型的時間部分,並進行比較。我找到了一種在StackOverflow中提取日期部分的方法。如果只有我一個人的日期部分,它只是從源日期時間減去日期:

datePortion = DATEADD(日,DATEDIFF(日,0,sourceDate),0)
timePortion = DATEDIFF(毫秒, datePortion,sourceDate

所以以提取在SQL Server 2005中的時間部分的宏是:

F(X)= DATEDIFF(毫秒,DATEADD(天,DATEDIFF(日,0,sourceDate ),0),sourceDate

現在查詢以比較日期時間字段的時間部分,用12:30:50.400是:

SELECT * 
FROM Table1 
WHERE 
     DATEDIFF(millisecond, DATEADD(day, DATEDIFF(day, 0, DateTimeField), 0), DateTimeField) 
     > 
     DATEDIFF(millisecond, DATEADD(day, DATEDIFF(day, 0, '1900-01-01T12:30:50.400'), 0), '1900-01-01T12:30:50.400') 

我已經測試該查詢與其他類型的查詢,包括使用減法運算符( ' - ')和CONVERT。執行計劃比較表明,這是執行此操作最快的方法。我還測試了查詢執行的實際時間......沒有明顯的最快方法。

+0

要整理查詢,而不是提高性能,這是一個非常好的解決方案,如果你把它扔到UDF中。這樣你可以把它寫成WHERE dbo.GetTime(MyDateField)> = @ SomeTime'。 – Aaronaught 2010-01-04 21:25:31

+0

在開始時,我想知道是否可以獲得更多的性能只改變查詢。這是可能的,但不是那麼多,不到2%。我無法找到GetTime函數。 – 2010-01-04 21:54:51

1

其他人張貼形成查詢的替代方法,但我想的東西迴應你的第一段說:

下面的例子是一個非常漫長和做的可能不是快方式這個。

表現方面,如果您有一個DATEPART或10 DATEPARTS在那裏並不重要,事實上,你甚至有一個DATEPART是什麼會損害表現。

如果您需要按時比較,但沒有日期,那麼Lasse的評論是正確的錢 - 你需要規範化爲單獨的日期/時間列。實際上,SQL 2008引入了datetime類型,並建議您使用它們而不是datetime。你在SQL 2005中沒有這個,但是你可以用它來解決這個問題,比如說,一天中的一個ticks字段,以及一個強制日期列的所有dateparts爲零的檢查約束。

如果以後需要在完整日期+時間內執行過濾器,則很容易創建計算列,並且如果性能對於這些問題是個問題,則可以保留該列並在其上創建索引。

+0

你完全正確! =)我問了這個問題,因爲我想知道如何解決它,它的方式,而不改變數據庫。事實上,所有QUERY-ONLY解決方案都是相同的速度順序,無論如何,所有速度都會變慢......我現在測試它......但使用DATEADD和DATEDIFF是最差的。 – 2010-01-04 20:45:51