约会结果(浮动)到最近的半小时

时间:2017-01-25 16:02:09

标签: sql-server

我正在计算两个小时间的小时数。客户希望将小时数四舍五入到最近的半小时。我的计算是:

hours = datediff(mi,ActualStart,ActualEnd)/60.0

这给了我一个漂浮物,我不能绕过时间四舍五入的方式。我知道如何围绕开始和结束时间,但宁愿将舍入应用于总小时数。

我正在使用SQL Server 2012

3 个答案:

答案 0 :(得分:3)

DATEADD( minute, ( DATEDIFF( minute, 0,                          dateTimeX   ) / 30 ) * 30, 0 ) AS dateTimeRoundDown,
DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute, 30 / 2, dateTimeX ) ) / 30 ) * 30, 0 ) AS dateTimeRoundNearest,
DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute, 30    , dateTimeX ) ) / 30 ) * 30, 0 ) AS dateTimeRoundUp

有关详细信息,请参阅this SO question & answer

单元测试

DECLARE @start DATETIME  = '2017-04-20 21:00:00'
DECLARE @end   DATETIME  = '2017-04-20 23:00:00'

;WITH CTE_dateTimes AS
(
    SELECT @start AS dateTimeX
    UNION ALL
    SELECT DATEADD( minute, 1, dateTimeX )
    FROM CTE_dateTimes
    WHERE DATEADD( minute, 1, dateTimeX ) <= @end
)
SELECT dateTimeX,
   DATEADD( minute, ( DATEDIFF( minute, 0,                          dateTimeX   ) / 30 ) * 30, 0 ) AS dateTimeRoundDown,
   DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute, 30 / 2, dateTimeX ) ) / 30 ) * 30, 0 ) AS dateTimeRoundNearest,
   DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute, 30    , dateTimeX ) ) / 30 ) * 30, 0 ) AS dateTimeRoundUp

FROM CTE_dateTimes
OPTION ( MAXRECURSION 200 )

答案 1 :(得分:0)

这是你可以实现目标的一种方式,这应该足以让你开始解决问题:

declare @t table(s datetime, e datetime);
insert into @t values
 ('20170125 01:00:00','20170125 01:10:00'),('20170125 01:00:00','20170125 01:15:00'),('20170125 01:00:00','20170125 01:25:00'),('20170125 01:00:00','20170125 01:40:00'),('20170125 01:00:00','20170125 01:55:00'),('20170125 01:00:00','20170125 02:05:00'),('20170125 01:00:00','20170125 02:55:00'),('20170125 01:00:00','20170125 04:14:00'),('20170125 01:00:00','20170125 22:05:00');

select datediff(mi,s,e) as MinutesDiff

        ,datediff(mi,s,e) / 60 as HoursDiff
        ,datediff(mi,s,e) % 60 as MinutesRemain

        -- Take the Minutes Remaining after all the full hours are removed,
        -- and integer divide by 15 to get the number of full quarter hours
        -- and then round to the nearest number of minutes to add on.
        ,case round(datediff(mi,s,e) % 60 / 15,0)
            when 0 then 0
            when 1 then 30
            when 2 then 30
            when 3 then 60
            end as MinutesRounded
from @t;

输出:

+-------------+-----------+---------------+----------------+
| MinutesDiff | HoursDiff | MinutesRemain | MinutesRounded |
+-------------+-----------+---------------+----------------+
|          10 |         0 |            10 |              0 |
|          15 |         0 |            15 |             30 |
|          25 |         0 |            25 |             30 |
|          40 |         0 |            40 |             30 |
|          55 |         0 |            55 |             60 |
|          65 |         1 |             5 |              0 |
|         115 |         1 |            55 |             60 |
|         194 |         3 |            14 |              0 |
|        1265 |        21 |             5 |              0 |
+-------------+-----------+---------------+----------------+

答案 2 :(得分:0)

试试这个:

 round( 48 * ( cast(ActualEnd as float)-cast(ActualStart as float) ),0) /2.0 as HoursRoundedToHalfHour,

将日期时间值转换为float会显示自特定日期以来的天数。

从另一个中减去一个给出两个日期时间之间的天数。

乘以48得到半小时的间隔数。

调用Round(x,0)将其舍入为最接近的整数。

除以2.0会将其转换为小时数。

示例:

create table Times ( ActualStart smalldatetime, ActualEnd smalldatetime )


insert into Times values
 ('20170125 01:00:00','20170125 01:10:00'),('20170125 01:00:00','20170125 01:15:00'),('20170125 01:00:00','20170125 01:25:00'),('20170125 01:00:00','20170125 01:40:00'),('20170125 01:00:00','20170125 01:55:00'),('20170125 01:00:00','20170125 02:05:00'),('20170125 01:00:00','20170125 02:55:00'),('20170125 01:00:00','20170125 04:14:00'),('20170125 01:00:00','20170125 22:05:00');


select 
  ActualStart,ActualEnd, 
  datediff(mi,ActualStart,ActualEnd) as [Minutes], 
  datediff(mi,ActualStart,ActualEnd)/60 as [Hr],       
  datediff(mi,ActualStart,ActualEnd)%60 as [Min],
  round( 48 * ( cast(ActualEnd as float)-cast(ActualStart as float) ),0) /2.0 as [HoursRoundedToHalfHour]
from Times


ActualStart             ActualEnd               Minutes     Hr          Min         HoursRoundedToHalfHour
----------------------- ----------------------- ----------- ----------- ----------- ----------------------
2017-01-25 01:00:00     2017-01-25 01:10:00     10          0           10          0
2017-01-25 01:00:00     2017-01-25 01:15:00     15          0           15          0.5
2017-01-25 01:00:00     2017-01-25 01:25:00     25          0           25          0.5
2017-01-25 01:00:00     2017-01-25 01:40:00     40          0           40          0.5
2017-01-25 01:00:00     2017-01-25 01:55:00     55          0           55          1
2017-01-25 01:00:00     2017-01-25 02:05:00     65          1           5           1
2017-01-25 01:00:00     2017-01-25 02:55:00     115         1           55          2
2017-01-25 01:00:00     2017-01-25 04:14:00     194         3           14          3
2017-01-25 01:00:00     2017-01-25 22:05:00     1265        21          5           21