2011-03-25 23 views
8

我與T-SQL的工作在SQL Server 2000和我有有定義爲DateTime的日期列TRANDATE,這是無關這個問題,許多其他的列中的表TRANSACTIONS ..T-SQL的日期的混亂

該表填充了跨越多年的事務。我遇到了代碼,測試,這讓我感到困惑。有一個簡單的SELECT,就像這樣:

SELECT TRANDATE, RECEIPTNUMBER FROM TRANSACTIONS WHERE TRANDATE BETWEEN '12/01/2010' and '12/31/2010' ORDER BY TRANDATE 

和它沒有返回兩行數據,我知道是該表。

通過上面的語句,最後一排的迴歸,才能,有一個TRANDATE的:2010-12-31 00:00:00.000

當我修改的聲明類似下面,我得到了額外的兩行2010年12月是該表:

SELECT TRANDATE, RECEIPTNUMBER FROM TRANSACTIONS WHERE TRANDATE BETWEEN '12/01/2010 00:00:00' and '12/31/2010 23:59:59' ORDER BY TRANDATE 

我試圖找出爲什麼BETWEEN操作犯規包括在12/31/2010爲24期間,所有行使用第一SELECT時,上面。爲什麼它需要在第二條修改後的語句中添加明確的小時數(如SELECT)以使其將正確的行數拉出?

是不是因爲TRANDATE被定義爲「DATETIME」?

基於這一發現,我認爲將不得不經歷所有這些舊代碼,因爲這些BETWEEN運算符在整個這個舊系統中都是散佈的,看起來好像它沒有正確地提取所有數據。我只是想先從一些人身上作出澄清。謝謝!

+4

''12/31/2010 23:59:59''仍然會錯過'2010年12月31日23:59:59'和2010年12月31日23:59:59:997之間的時間在''之間'使用''日期時間使用'> =和<'來代替。 – 2011-03-25 14:55:25

+1

@Martin:謝謝。並感謝所有其他人。特別是@GSerg誰基本上回答了我的問題。 我似乎不能upvote,直到我有15分,這就是爲什麼你都沒有看到任何(從我)。但現在我明白基於每個人的反應。謝謝。我有一些工作要做! :-) – ONDEV 2011-03-25 15:00:39

回答

14

一個日期是一個時間點,而不是一個時間跨度。

'12/31/2010'也是一個觀點。也就是十二月三十一號的午夜。
在這一點之後發生的一切都被忽略。
這正是你想要的行爲(即使還沒有意識到)。

不要以爲當你選擇省略時間部分時,它奇蹟般地被認爲是"any"。這將是"all zeroes",也就是午夜。

2

什麼是您預期的結果,如果我會做這個

Insert "12/31/2010" into your datetime column? 

沒錯:2010年12月31日00:00:00

爲什麼你會想到它是作爲參數的不同一個問題?

1

你有回答你自己的問題。你觀察到的 SQL Server的工作方式。

如果確認你的需要,這個MSDN document有以下一下說

當時間部分是不確定的,它 默認爲凌晨12:00請注意,包含時間部分 的行 上午12:00之後。在1998-0105將 不會由此查詢返回,因爲 它不在範圍內。

編輯

至於你的評論,日期時間本質上是一個浮點值。

以下腳本顯示SQL Server使用的數字。
40541。9749(12/31/2010 23時23分59秒)不能被包含時你的上限是40541(12/31/2010)

DECLARE @ADateTime1 DATETIME 
DECLARE @ADateTime2 DATETIME 
DECLARE @ADateTime1AsFloat FLOAT 
DECLARE @ADateTime2AsFloat FLOAT 

SET @ADateTime1 = '12/31/2010' 
SET @ADateTime2 = '12/31/2010 23:23:59' 

SET @ADateTime1AsFloat = CAST(@ADateTime1 AS FLOAT) 
SET @ADateTime2AsFloat = CAST(@ADateTime2 AS FLOAT) 

SELECT @ADateTime1AsFloat, @ADateTime2AsFloat 
+0

好的,但那是我的困惑。你是對的,我似乎'理解'它在做什麼,但是爲什麼我有什麼困惑...... 12/31/2010有24小時的時間,如果我有一排數據與2010-12的TRANDATE -31 18:12:54.000,爲什麼BETWEEN(沒有小時數)選擇那個? 12/31/2010還是12/31/2010無論時間是00:00:00還是18:12:54或者23:59:59! – ONDEV 2011-03-25 14:58:01

3

'12/01/2010'意思是'12/01/2010 00:00:00'和'12/31/2010'意思是'12/31/2010 00:00:00'。這就是爲什麼日期時間值在2010年12月31日當天晚些時候被排除在查詢結果之外的原因。

4

正如您發現的那樣,如果您在輸入日期時未指定時間,則默認爲日期早上的午夜。所以2010年12月31日在午夜時分停止。

要獲得所有日期12/31/2010,你可以或者指定的時間,因爲你所做的一切,或添加一天的結束日期。沒有時間,2011年1月1日在2010年12月31日午夜時分結束。所以,你可以做BETWEEN 12/1/2010 AND 1/1/2011。如果這樣做更容易,可以使用DATEADD在SQL中添加日期。

添加一天的第二種方法存在一些風險。您將獲得1/1/2011的任何記錄,其時間爲00:00:00。

這裏的執行DATEADD一個辦法:

DECLARE @FromDate datetime, @ToDate datetime 
// These might be stored procedure input parameters 
SET @FromDate = '12/1/2010' 
SET @ToDate = '12/31/2010' 

SET @ToDate = DATEADD(d, 1, @ToDate) 

然後你在WHERE子句中BETWEEN短語通常的方法使用@ToDate