2017-01-25 127 views
0

我正在計算兩個小日期的小時數。客戶希望將時間舍入到最近的半小時。我的計算是:datediff(浮動)到最近的半小時的整體結果

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

這給了我一個浮動,我不能把時間四捨五入。我知道如何將開始時間和結束時間四捨五入,但寧可將舍入應用於總時數。

我使用的是SQL Server 2012的

+0

你是如何做的四捨五入?總是上升或下降到下一個30分鐘,或者你是否有一箇中值截止點,其中下方向下取整,上方向上取整? – iamdave

回答

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 | 
+-------------+-----------+---------------+----------------+ 
+0

謝謝,我能夠使用它。它允許我將我的開始和結束時間存儲爲變量,以便我可以使用帶有掩碼的文本框來輸入它們。 – brndnmlk

0

試試這個:

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

將日期時間值轉換爲浮點值可以爲您提供自特定日期以來的天數。

從一個減去另一個給出兩個日期之間的天數。

乘以48得到半小時間隔的數量。

調用舍入(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 
2
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) 
相關問題