在 MS SQL / SQL Server 2005 中精确限制日期范围
-
03-07-2019 - |
题
我想限制报告返回从日期 A 到日期 B 的记录。这就是我一直在做的事情:
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
...我被告知返回了从 1 月 1 日上午 12 点到 3 月 31 日晚上 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 会将百分之一秒四舍五入一半。所以我得到了 4 月 1 日的记录(哈!愚人节记录!grr) 如果我使用晚于 11:59:29 的任何时间。这是为什么?
- (我确信有。我对此很陌生。感谢您的帮助!)
解决方案
总是有简单的选择:
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
其他提示
我怀疑 view_Inspections 中的日期列是 SmallDateTime 数据类型。此数据类型的精度为 1 分钟,这解释了您的意外结果(将秒四舍五入到最接近的分钟)。
Roland Shaw 建议的方法是修改查询以满足您的要求的最佳方法。
BETWEEN 运算符具有包容性,这就是您在第一个查询中看到结果的原因。您在第二个查询中看到的舍入将取决于您在表中使用的确切日期时间数据类型。(顺便说一句,我认为你混淆了秒和百分之一秒)。看起来您可能在表中使用了smalldatetime,在这种情况下,时间将四舍五入到最接近的分钟。
如果您的表使用日期时间,请尝试将 @startDate 和 @endDate 显式转换为 DATETIME 值 (CAST(@endDate AS DATETIME))。
快速说明...即使对于 DATETIME 值,SQL Server 也只能精确到 3/100 秒,因此 11:59:59.999 将向上舍入为 12:00:00.000。
你基本上有三个选择:
1) 在 CAST('01/01/2008 00:00:00.000' AS DATETIME) 和 CAST('03/31/2008 12:59:59.997' AS DATETIME) 之间
2) 年(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)
我认为第一种方法不太直观并且容易出错。第二种方法会降低性能,因为无法使用索引,并且如果您可以进行跨越数年或在几个月中开始/结束的搜索,它会变得更加复杂。罗兰建议的第三种方法是我认为最好的。
只需尝试从日期字段中删除时间,如下所示:
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:00
到 04/01/2008 11:59:59.999
。如果你不想 04/01
包括在内,将您的结束日期更改为 03/31/2008
.
最好的解决方案是创建一个名为“julian”的 BIGINT(10) 字段,并将其存储在 YYYYMMDD 中。
然后执行查询 其中 julian >= '20120103' 和 julian <= '20120203'