四舍五入到最接近的 15 分钟间隔
Round to nearest 15 minute interval
我已经看到这个问题被询问并回答了存储为日期的时间,但我将小时和分钟的持续时间存储为 numeric(4,2)
。例如2.12,就是2小时12分钟。我需要将其四舍五入到最接近的 15 分钟间隔,这样做 (CONVERT([numeric](4,2),round(2.12/(25),(2))*(25)))
不起作用,因为它以 10 为基数并且四舍五入时间不正确。非常感谢任何帮助,谢谢。
编辑:我从示例中寻找的结果是 2.25
。
对于我的用例,持续时间需要以季度表示,
15 分钟 = .25
30 分钟 = .50
45 分钟 = .75
您不能对持续时间进行任何计算,因为它不是以 10 为基数,将其转换为以 10 为基数可能会导致精度丢失(例如 2 小时 1 分钟,您的格式为 2.01,转换为 2.01666666 ...)
最好将其转换为总分钟数,然后四舍五入并转换回您的格式
declare @duration numeric(4,2) = 2.12;
with
cte1 as
(
select tot_mins = (floor(@duration) * 60)
+ (@duration * 100) % 100
),
cte2 as
(
select *, tot_mins_rounded = round(tot_mins / 15.0, 0) * 15
from cte1
)
select *,
convert_back_to_your_format = floor(tot_mins_rounded / 60)
+ (tot_mins_rounded % 60) / 100.0
from cte2
结果:
tot_mins
tot_mins_rounded
convert_back_to_your_format
132.00
135.000000
2.15000000000
理想情况下,您不会将持续时间存储为小数 - 如果总是少于 24 小时,则应存储为 time
,如果可能多天,则应存储为 datetime2
。
通过以可接受的时间格式转换为字符串来转换为时间。然后使用找到的您最喜欢的解决方案 here.
select
-- Original Value
D.[Value]
-- As Time
, T.[Time]
-- As Time Rounded
, RT.[Time]
-- As decimal
, convert(decimal(9,2),datepart(hour,RT.[Time]) + datepart(minute,RT.[Time]) / 60.0)
from (
-- Test Values
values (2.12), (2.02), (0.12)
) D ([Value])
cross apply (
-- Convert to time datatype
values (convert(time(0), convert(varchar(8),convert(int, D.[Value])) + ':' + substring(convert(varchar(8),D.[Value] - convert(int, D.[Value])),3,8)))
) T ([Time])
cross apply (
-- Round using your favourite method
values (convert(time(0), dateadd(minute, round(datediff(minute, 0, T.[Time]) / 15.0, 0) * 15, 0)))
) RT ([Time]);
还有一个选择
declare @YourTable table (duration numeric(4,2))
Insert Into @YourTable values
( 2.12 )
,( 1.30 )
,( 1.55 )
Select Duration
,NewValue = floor(duration) + ceiling(((duration % 1) * 100 / 60 ) * 4) / 4
From @YourTable
结果
Duration NewValue
2.12 2.250000
1.30 1.500000
1.55 2.000000
我已经看到这个问题被询问并回答了存储为日期的时间,但我将小时和分钟的持续时间存储为 numeric(4,2)
。例如2.12,就是2小时12分钟。我需要将其四舍五入到最接近的 15 分钟间隔,这样做 (CONVERT([numeric](4,2),round(2.12/(25),(2))*(25)))
不起作用,因为它以 10 为基数并且四舍五入时间不正确。非常感谢任何帮助,谢谢。
编辑:我从示例中寻找的结果是 2.25
。
对于我的用例,持续时间需要以季度表示,
15 分钟 = .25
30 分钟 = .50
45 分钟 = .75
您不能对持续时间进行任何计算,因为它不是以 10 为基数,将其转换为以 10 为基数可能会导致精度丢失(例如 2 小时 1 分钟,您的格式为 2.01,转换为 2.01666666 ...)
最好将其转换为总分钟数,然后四舍五入并转换回您的格式
declare @duration numeric(4,2) = 2.12;
with
cte1 as
(
select tot_mins = (floor(@duration) * 60)
+ (@duration * 100) % 100
),
cte2 as
(
select *, tot_mins_rounded = round(tot_mins / 15.0, 0) * 15
from cte1
)
select *,
convert_back_to_your_format = floor(tot_mins_rounded / 60)
+ (tot_mins_rounded % 60) / 100.0
from cte2
结果:
tot_mins | tot_mins_rounded | convert_back_to_your_format |
---|---|---|
132.00 | 135.000000 | 2.15000000000 |
理想情况下,您不会将持续时间存储为小数 - 如果总是少于 24 小时,则应存储为 time
,如果可能多天,则应存储为 datetime2
。
通过以可接受的时间格式转换为字符串来转换为时间。然后使用找到的您最喜欢的解决方案 here.
select
-- Original Value
D.[Value]
-- As Time
, T.[Time]
-- As Time Rounded
, RT.[Time]
-- As decimal
, convert(decimal(9,2),datepart(hour,RT.[Time]) + datepart(minute,RT.[Time]) / 60.0)
from (
-- Test Values
values (2.12), (2.02), (0.12)
) D ([Value])
cross apply (
-- Convert to time datatype
values (convert(time(0), convert(varchar(8),convert(int, D.[Value])) + ':' + substring(convert(varchar(8),D.[Value] - convert(int, D.[Value])),3,8)))
) T ([Time])
cross apply (
-- Round using your favourite method
values (convert(time(0), dateadd(minute, round(datediff(minute, 0, T.[Time]) / 15.0, 0) * 15, 0)))
) RT ([Time]);
还有一个选择
declare @YourTable table (duration numeric(4,2))
Insert Into @YourTable values
( 2.12 )
,( 1.30 )
,( 1.55 )
Select Duration
,NewValue = floor(duration) + ceiling(((duration % 1) * 100 / 60 ) * 4) / 4
From @YourTable
结果
Duration NewValue
2.12 2.250000
1.30 1.500000
1.55 2.000000