【问题标题】:SQL Server : decimal difference in timeSQL Server:时间的十进制差异
【发布时间】:2018-09-27 16:52:21
【问题描述】:

我正在尝试转换小数小时时差,但总是四舍五入导致问题。

declare @Accrued decimal(9,4) = 24.60
declare @Used decimal(9,4) = 23.5734
declare @Remaining decimal(9,2) = @Accrued -  @Used

declare @RoundAccrued decimal(9,2) = ceiling(@Accrued * 100) /  100
declare @RoundUsed decimal(9,2) =  ceiling(@Used * 100) /  100
declare @RoundRemaining decimal(9,2) =  ceiling(@Remaining * 100) /  100

declare @hrAcc int = @Accrued
select left(cast (@hrAcc as varchar), 4) + '.' + right('0' + cast((floor((@RoundAccrued * 60) % 60)) as varchar), 2) Accrued

declare @hrUsed int = @Used
select left(cast (@hrUsed as varchar), 4) + '.' + right('0' + cast((floor((@RoundUsed * 60) % 60)) as varchar), 2) Used
declare @hrRem int = @Remaining
select  left(cast (@hrRem as varchar), 4) + '.' + right('0' + cast((floor((@RoundRemaining * 60) % 60)) as varchar), 2) Remaining

结果

  • 应计:24.36
  • 使用时间:23.34
  • 剩余:1.01(而不是 1.02)

它在AccruedUsed 上完美运行,但无论我做什么,它仍然比不同的时间短一分钟或更多。

【问题讨论】:

    标签: sql sql-server time decimal


    【解决方案1】:

    这一切都是因为使用了圆角、天花板和地板。

    您可以使用以下内容:

    select convert(varchar(10), @hrAcc) + '.'+ right('0' + cast(cast((@Accrued-@hrAcc)*60 as int) as varchar),2)
    select convert(varchar(10), @hrUsed) + '.'+ right('0' + cast(cast((@Used-@hrUsed)*60 as int) as varchar),2)
    select cast((abs(cast(@hrAcc*60+cast((@Accrued-@hrAcc)*60 as int) as int) - cast(@hrUsed*60+cast((@Used-@hrUsed)*60 as int) as int)))/60 as varchar)
        +'.'
        + cast((abs(cast(@hrAcc*60+cast((@Accrued-@hrAcc)*60 as int) as int) - cast(@hrUsed*60+cast((@Used-@hrUsed)*60 as int) as int)))%60 as varchar)
    

    ---测试(使用舍入值而不是原始值)

     declare @Accrued decimal(9,4) = 0.5333--106.325--106.325--51.2568--49.9217--106.325--49.9217--24.60
        declare @Used decimal(9,4) = 0.0333--87.885--87.885--49.9217--51.2568--87.88--51.2568--23.5734
        declare @Remaining decimal(9,4) = @Accrued -  @Used
    declare @hrAcc int = @Accrued
    declare @hrUsed int = @Used
    declare @hrRem int = @Remaining 
    
    declare @RoundAccrued decimal(9,4) = ceiling(@Accrued * 100) /  100
    declare @RoundUsed decimal(9,4) =  ceiling(@Used * 100) /  100
    declare @RoundRemaining decimal(9,4) =  ceiling(@Remaining * 100) /  100
    
    select convert(varchar(10), @hrAcc) + '.'+ right('0' + cast(cast((@RoundAccrued-@hrAcc)*60 as int) as varchar),2) Accrued
    select convert(varchar(10), @hrUsed) + '.'+ right('0' + cast(cast((@RoundUsed-@hrUsed)*60 as int) as varchar),2) Used
    select cast((abs(cast(@hrAcc*60+cast((@RoundAccrued-@hrAcc)*60 as int) as int) - cast(@hrUsed*60+cast((@RoundUsed-@hrUsed)*60 as int) as int)))/60 as varchar)
        +'.'
        + cast((abs(cast(@hrAcc*60+cast((@RoundAccrued-@hrAcc)*60 as int) as int) - cast(@hrUsed*60+cast((@RoundUsed-@hrUsed)*60 as int) as int)))%60 as varchar) Remaining
    

    【讨论】:

    • 我试过没有天花板或地板,但结果是一样的。
    • 当它变为负数时失败应计:49.9217 和使用:51.2568。除了目前为其他数字工作的负数。
    • Also Accrued:106.325 and Used:87.885 剩余返回 18.66 而不是 18h.26m
    • 非常感谢我从昨天开始就一直在测试它,它就像一个魅力。
    • 我将 decimal(9,2) 更改为 decimal(9,4) 似乎可以正常工作,请尝试。
    【解决方案2】:

    使用秒应该足够了。所以试试这个:

    select cast(dateadd(second, @Remaining*60*60, 0) as time)
    

    这将结果作为时间数据类型。请注意,此类型仅限于 24 小时。

    【讨论】:

    • 我需要使用小数来累积所有应计小时数,例如 136.89 应计和 129.89 已使用。
    • @JOZO 。 . .那么你不能在 SQL Server 中使用time 来表示金额。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多