2009-01-05 50 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'