【问题标题】:Trouble converting from time to decimal time麻烦从时间转换为十进制时间
【发布时间】:2014-03-21 20:15:27
【问题描述】:

我得到的部分任务涉及对几列执行计算,其中 2 列是 hh.mi.ss 格式,它们是 varchar。为了使计算工作,我需要将它们转换为时间十进制格式,其中 1:30 将是 1.5 。由于我目前使用的是 SQL Server 2005,因此我没有内置时间或数据类型,也无法获得升级版本(不是我的选择)。使用我所拥有的,我在网上搜索并尝试转换它,但结果不准确。例如,13.28 变为(大致)13.5,这很好,但是,秒数变为 100 而不是以 60 结束(因为我将其转换为浮点数)。

例如,使用 12.57.46,

CAST(DATEPART(HH, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME)) AS FLOAT) + 
(CAST(DATEPART(MI, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME)) AS FLOAT)/60) + 
(CAST(DATEPART(SS, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME)) AS FLOAT)/3600)

给了我 12.962...

CAST(SUBSTRING([OASTIM], 1, 2) AS FLOAT) +
((CAST(SUBSTRING([OASTIM], 4, 5) AS FLOAT) + 
CAST(SUBSTRING([OASTIM], 7, 8) AS FLOAT)/60)/60)

给了我 12.970....

当我尝试更简单的方法时,

DATEPART(HOUR, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME))+
(DATEPART(MINUTE, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME))/60)

失败了,只给了我 12 个

这是我第一次接触 Windows SQL 和 T-SQL,我已经为此苦苦挣扎了几个小时。尽管听起来很可怕,但我现在对它的工作感到满意,即使这意味着牺牲性能。

【问题讨论】:

    标签: sql sql-server tsql datetime-conversion


    【解决方案1】:

    您没有解释什么是“时间小数”格式。从您的示例中,我猜您的意思是十进制小时数。

    SQL Server 中用于日期差异的关键函数是datediff()。您可以使用技巧将时间转换为秒。将时间添加到日期,然后使用datediff() 获取午夜后的秒数。之后,转换为十进制小时只是算术。

    这是一个例子:

    select datediff(second,
                    cast('2000-01-01' as datetime),
                    cast('2000-01-01 ' + '00:00:59' as datetime)
                   )/3600.0 as DecimalHours
    

    注意常量3600.0的使用。小数点非常重要,因为 SQL Server 对整数输入进行整数除法。所以,1/20,而不是0.5

    【讨论】:

    • 我注意到您使用的是日期,并且我确实有一个与我的时间列相对应的日期列(是的,它们是分开的,两者都是 varchars,但日期的格式为 YYYY-MM -DD)。当我的意思是“时间十进制格式”时,我的意思是十进制小时数。
    • @CuckoOooo 。 . .这使用任意日期只是为了轻松地将时间转换为秒。除非您出于某种原因需要它,否则它不会使用日期列。
    • 我从老板那里得到了更新,他确实希望我将日期纳入我的计算中。我放弃了我的子字符串方法,并决定将你的方法与 datediff 一起使用,因为它更干净。为了比较的目的,我做了一些手动计算后,结果是正确的,所以我接受了你的回答。
    【解决方案2】:

    你说,

    CAST(SUBSTRING([OASTIM], 1, 2) AS FLOAT) +
    ((CAST(SUBSTRING([OASTIM], 4, 5) AS FLOAT) + 
    CAST(SUBSTRING([OASTIM], 7, 8) AS FLOAT)/60)/60)
    

    给了我 12.970....

    对于“12.57.46”的输入,12.970 是错误的。问题是您错误地使用了 SUBSTRING 函数。第三个参数表示字符的数量,而不是结束字符的位置。

    看看这段代码:

    声明@Sample varchar(20)

    设置@Sample = '12.57.46'

    select  CAST(SUBSTRING(@Sample, 1, 2) AS FLOAT) +
            CAST(SUBSTRING(@Sample, 4, 5) AS FLOAT) / 60 + 
            CAST(SUBSTRING(@Sample, 7, 8) AS FLOAT) / 60 / 60,
            SUBSTRING(@Sample, 1, 2),
            SUBSTRING(@Sample, 4, 5),
            SUBSTRING(@Sample, 7, 8),
            CAST(SUBSTRING(@Sample, 1, 2) AS FLOAT) +
            CAST(SUBSTRING(@Sample, 4, 2) AS FLOAT) / 60 + 
            CAST(SUBSTRING(@Sample, 7, 2) AS FLOAT) / 60 / 60
    

    请注意,分钟数显示为 57.46,因为您要求输入 5 个字符。秒数显示正确,因为即使您要求输入 8 个字符,但字符串中只剩下 2 个字符,因此只返回这 2 个字符。

    顺便说一句,我会像 Gordon 那样解决这个问题,只是我会删除日期内容,所以它看起来像这样:

    Select DateDiff(Second, 
                    0, 
                    Convert(DateTime, Replace([OASTIM], '.',':'))) / 3600.0
    

    【讨论】:

    • @G Mastros 啊,我知道我在哪里搞砸了,谢谢!顺便说一句,我从老板那里得到了更新,他希望我将日期纳入我的计算中。例如,如果时间相同但日期不同,则结果不应为 0,而应为这两个日期之间的小数小时数。我想我可以使用 datediff 函数让它工作,因为它看起来比使用子字符串更干净。
    【解决方案3】:

    这是将时间转换为 DecimalHours 的简单方法。

    SELECT cast(cast('12.57:46' as datetime) as float) * 24
    

    结果:

    ~12.963
    

    【讨论】:

      猜你喜欢
      • 2016-05-09
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 2021-07-22
      • 2011-07-09
      • 2014-03-13
      相关资源
      最近更新 更多