我正在使用MsSQL Server几天了,当将日期时间转换为/从小数时,偶然发现了一种奇怪的行为。
SELECT [date] = GETDATE()
, [as decimal] = CAST(GETDATE() AS decimal)
, [from decimal] = CAST(CAST(GETDATE() AS decimal) AS datetime)
, [as float] = CAST(GETDATE() AS float)
, [from float] = CAST(CAST(GETDATE() AS float) AS datetime)
-- should be: 2009-08-15
, [from stored float] = CAST(CAST('40039.9583333333' AS float) AS datetime)
当我转换日期时间而不添加任何特定的小数时,将处理小数,因为我将其定义为十进制(18,0)。 So there is a data loss in some way.
如果我直接将一个浮点数转换回从日期时间转换的日期时间(如我的查询的第7行所示),一切都很好。
但是当我从数据库表中加载一个值时,例如40039.9583333333,它肯定是从用户输入(2009-08-15)计算出来并将其转换回日期时间,它会添加一天。
我无法找到任何具体的时间损失。
有人能够描述这种奇怪行为背后的问题吗? 并且,如果可能的话 添加一个关于如何正确执行这些转换的示例?
感谢。
答案 0 :(得分:1)
我使用了您指定的值' 2009-08-15'并将其转换为十进制和浮点数,两者的值均为40038。我使用此值转换回日期时间,并且十进制和浮点数返回' 2009-08-15 00:00:00.000'。
值40039.9583333333导致,正如Renan刚刚发布的那样:),' 2009-08-16 22:59:59.997'。
我会怀疑它是否绝对是根据用户输入计算的(2009-08-15)'因为事实并非如此。除此之外还有更多内容。
-- Microsoft SQL Server 2014 - 12.0.4100.1 (X64)
DECLARE @dt datetime = '2009-08-15'
SELECT CAST(@dt AS decimal) -- 40038
SELECT CAST(@dt AS float) -- 40038
DECLARE @dec1 decimal = 40038;
SELECT CAST(@dec1 AS datetime) -- 2009-08-15 00:00:00.000
DECLARE @flo1 float = 40038;
SELECT CAST(@flo1 AS datetime) -- 2009-08-15 00:00:00.000
DECLARE @dec2 decimal = 40039.9583333333;
SELECT CAST(@dec2 AS datetime) -- 2009-08-17 00:00:00.000
DECLARE @flo2 float = 40039.9583333333;
SELECT CAST(@flo2 AS datetime) -- 2009-08-16 22:59:59.997
答案 1 :(得分:0)
您在数据库中的输入源是什么?根本问题可能是该日期的起始参考点。
作为一个例子:从在线阅读,在Excel中的日期值' 1900-01-01'在数字上等于1。
但是,在SQL Server中日期值' 1900-01-01'在数字上等于0。
SELECT CAST(CAST('1900-01-01' AS DATETIME) AS FLOAT)
答案 2 :(得分:0)
在SQL Server中40039.9583333333
是SELECT CAST(CAST('2009-08-16 23:00' AS DATETIME) AS FLOAT)
您应该检查输入。检查正在使用的比例/代码来计算存储在表格中的值。