为什么 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”的时间部分。

MSDN

Demo

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;