为什么 SQL 将确切的日期时间更改一个刻度
Why SQL changes the exact datetime by one tick
DECLARE @dateEnd datetime
SET @dateEnd = '2014-11-30T23:59:59.999'
SELECT @dateEnd
为什么我得到结果:
2014-12-01 00:00:00.000
我想为 SELECT 条件使用变量:
where [MyDate] between @dateStart and @dateEnd
这是另一个相关的问题。我希望包含第一个数据点 (dataStart),将第二个数据点 (dataEnd) 从所选数据范围中排除。怎么做?
datetime
的时间范围是“00:00:00 到 23:59:59.997”。在“.999”处,此值会四舍五入到最接近的秒数,这恰好是第二天的开始,从而导致所描述的结果。不过,为了记录,“.998”将保留同一天的“23:59:59”的时间部分。
Sql 服务器日期时间数据类型的精度
只是为了详细说明 shree.pat 的回答,Sql 服务器的 DATETIME data type 的分辨率为 300 'steps' 或每 1 秒的量程,或分辨率间隔为~3 毫秒。
这意味着 DATETIME
无法准确表示 1 毫秒精度的时间瞬间。在此处的示例中,2014-11-30T23:59:59.999
将四舍五入为 2014-12-01 00:00:00.000
。同样,在 1 毫秒之前,2014-11-30T23:59:59.998
将四舍五入为 2014-11-30T23:59:59.997
.
此查询演示了 DateTime
与实际时间相比如何舍入毫秒数:
WITH cteMS AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY o1.object_id) as MilliSeconds
FROM sys.objects o1 CROSS JOIN sys.objects o2
)
SELECT DATEADD(ms, cteMS.MilliSeconds, CAST('2015-01-01' AS DATETIME2)) AS DT2,
DATEADD(ms, cteMS.MilliSeconds, CAST('2015-01-01' AS DATETIME)) AS DT
FROM cteMS;
如果您需要 1 毫秒或更好的精度,那么您应该使用 DATETIME2
数据类型,它可以表示低至 100ns
.
的精度
比较日期范围与 BETWEEN
的问题
根据 Damien 的评论,您的问题说明了为什么使用 BETWEEN
搜索两个日期之间的数据不是一个好主意。
查询的准确性取决于日期类型,因为 where [MyDate] between @dateStart and @dateEnd
现在会根据 @dtStart
、@dtEnd
以及您输入的日期和时间列给出不同的结果比较。
相反,在下限(包括)上使用 >=
,在排除的上限上使用 <
,如下所示:
DECLARE @dateEnd AS DateTime, or DateTime2
SET @dateEnd = '2014-11-31';
SELECT ... WHERE [MyDate] >= @dateStart AND [MyDate] < @dateEnd;
DECLARE @dateEnd datetime
SET @dateEnd = '2014-11-30T23:59:59.999'
SELECT @dateEnd
为什么我得到结果:
2014-12-01 00:00:00.000
我想为 SELECT 条件使用变量:
where [MyDate] between @dateStart and @dateEnd
这是另一个相关的问题。我希望包含第一个数据点 (dataStart),将第二个数据点 (dataEnd) 从所选数据范围中排除。怎么做?
datetime
的时间范围是“00:00:00 到 23:59:59.997”。在“.999”处,此值会四舍五入到最接近的秒数,这恰好是第二天的开始,从而导致所描述的结果。不过,为了记录,“.998”将保留同一天的“23:59:59”的时间部分。
Sql 服务器日期时间数据类型的精度
只是为了详细说明 shree.pat 的回答,Sql 服务器的 DATETIME data type 的分辨率为 300 'steps' 或每 1 秒的量程,或分辨率间隔为~3 毫秒。
这意味着 DATETIME
无法准确表示 1 毫秒精度的时间瞬间。在此处的示例中,2014-11-30T23:59:59.999
将四舍五入为 2014-12-01 00:00:00.000
。同样,在 1 毫秒之前,2014-11-30T23:59:59.998
将四舍五入为 2014-11-30T23:59:59.997
.
此查询演示了 DateTime
与实际时间相比如何舍入毫秒数:
WITH cteMS AS
(
SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY o1.object_id) as MilliSeconds
FROM sys.objects o1 CROSS JOIN sys.objects o2
)
SELECT DATEADD(ms, cteMS.MilliSeconds, CAST('2015-01-01' AS DATETIME2)) AS DT2,
DATEADD(ms, cteMS.MilliSeconds, CAST('2015-01-01' AS DATETIME)) AS DT
FROM cteMS;
如果您需要 1 毫秒或更好的精度,那么您应该使用 DATETIME2
数据类型,它可以表示低至 100ns
.
比较日期范围与 BETWEEN
的问题根据 Damien 的评论,您的问题说明了为什么使用 BETWEEN
搜索两个日期之间的数据不是一个好主意。
查询的准确性取决于日期类型,因为 where [MyDate] between @dateStart and @dateEnd
现在会根据 @dtStart
、@dtEnd
以及您输入的日期和时间列给出不同的结果比较。
相反,在下限(包括)上使用 >=
,在排除的上限上使用 <
,如下所示:
DECLARE @dateEnd AS DateTime, or DateTime2
SET @dateEnd = '2014-11-31';
SELECT ... WHERE [MyDate] >= @dateStart AND [MyDate] < @dateEnd;