2009-01-05 83 views
1

我想限制的報告通過日期B.從日期返回記錄的正確性這是我一直在做的事情:限制日期範圍與MS SQL/SQL Server 2005的

declare @startDate varchar(20) 
declare @endDate varchar(20) 
set @startDate = '01/01/2008' 
set @endDate = '04/01/2008' 
-- test what are the start and end dates 
select min(date),max(date) from view_Inspections 
where date between @startDate and @endDate 

...我被告知從3月31日的凌晨1點到11點59分回覆了記錄(當沒有時間時,默認是午夜)。但是我注意到了一個差異,就是如果一個記錄的時間是00:00:00,那麼它將成爲這個集合的一部分。

是否有這樣做所以它會返回正是我想要的日期範圍的更精確的方式*

我試着使用時間:

declare @startDate varchar(20) 
declare @endDate varchar(20) 
set @startDate = '01/01/2008 00:00:00' 
set @endDate = '04/01/2008 11:59:59' 
-- test what are the start and end dates 
select min(date),max(date) from view_Inspections 
where date between @startDate and @endDate 

...但我注意到了一些靠不住的: SQL Server將把hundreth-second增加一半。因此,如果我晚於11:59:29使用任何時間,我會得到4月1日的紀錄(ha!April Fool's record!grr)。這是爲什麼?

  • (我覺得肯定有我新,在此感謝您的幫助。!)
+0

謝謝!這有很大幫助。 @ G-Mastros:這是SmallDateTime - 感謝您解釋這種數據類型的行爲! – aesdanae 2009-01-05 21:19:17

回答

5

人們總是容易的選擇:

declare @startDate varchar(20) 
declare @endDate varchar(20) 
set @startDate = '01/01/2008' 
set @endDate = '04/01/2008' 

-- test what are the start and end dates 
select min(date),max(date) from view_Inspections 
where date >= @startDate 
and date < @endDate 
+0

我建議您解釋BETWEEN/AND是包含性的,並且所需的搜索範圍是半開放(或半封閉),並且需要排除結束點。 – 2009-01-05 20:17:19

2

我懷疑日期view_Inspections中的列是SmallDateTime數據類型。該數據類型具有1分鐘的準確度,這解釋了您意想不到的結果(將秒數舍入到最接近的分鐘)。

Roland Shaw建議的方法是修改查詢以適應您的要求的最佳方法。

1

BETWEEN運算符是包容性的,這就是爲什麼你看到了你在第一個查詢中的結果。您在第二個查詢中看到的四捨五入取決於您在表中使用的確切日期時間數據類型。 (順便說一句,我認爲你把秒和百分之一秒混淆)。看起來你可能在你的表中使用了一個smalldatetime,在這種情況下,時間四捨五入到最接近的分鐘。

如果您的表使用的是datetime,請嘗試將@startDate和@endDate顯式轉換爲DATETIME值(CAST(@endDate AS DATETIME))。

快速提示...即使對於DATETIME值,SQL Server也只能精確到秒的3/100秒,因此11:59:59.999會四捨五入爲12:00:00.000。

你基本上有三種選擇:

1)之間進行轉換('01/01/2008 00:00:00.000' AS DATETIME)和CAST('03/31/2008 12:59:59.997' AS DATETIME)

2)YEAR(my_date)= 2008和月(my_date)1和3之間

3)my_date> = CAST('01/01/2008 00:00:00.000' AS DATETIME)AND my_date < CAST('04/01/2008 00:00:00.000'AS DATETIME)

第一種方法不是很直觀,而且是錯誤親ne在我看來。第二種方法會導致性能下降,因爲索引無法使用,並且如果您可以進行跨越數年或在數月中開始/結束的搜索,則會變得更加複雜。 Rowland建議的第三種方法是我認爲的最好的方法。

1

簡單地嘗試從日期字段刪除的時候,像這樣:

declare @startDate varchar(20) 
declare @endDate varchar(20) 
set @startDate = '01/01/2008' 
set @endDate = '04/01/2008' 

SELECT min(date),max(date) FROM view_Inspections 
WHERE CAST(FLOOR(CAST(date AS FLOAT)) AS DATETIME) BETWEEN CAST(@startDate AS DATETIME) And CAST(@startDate AS DATETIME)) 

這一切從迴歸到01/01/2008 00:00:0004/01/2008 11:59:59.999。 如果您不希望包含04/01,請將您的結束日期更改爲03/31/2008

+0

第二個CAST(@startDate AS DATETIME)應該是CAST(@endDate AS DATETIME) – 2010-11-01 20:49:05

0

您的最佳解決方案是創建一個名爲「julian」的BIGINT(10)字段,並將其存儲在YYYYMMDD中。

然後做查詢 其中朱利安> = '20120103' 和Julian < = '20120203'