我正在計算兩個小日期的小時數。客戶希望將時間舍入到最近的半小時。我的計算是:datediff(浮動)到最近的半小時的整體結果
hours = datediff(mi,ActualStart,ActualEnd)/60.0
這給了我一個浮動,我不能把時間四捨五入。我知道如何將開始時間和結束時間四捨五入,但寧可將舍入應用於總時數。
我使用的是SQL Server 2012的
我正在計算兩個小日期的小時數。客戶希望將時間舍入到最近的半小時。我的計算是:datediff(浮動)到最近的半小時的整體結果
hours = datediff(mi,ActualStart,ActualEnd)/60.0
這給了我一個浮動,我不能把時間四捨五入。我知道如何將開始時間和結束時間四捨五入,但寧可將舍入應用於總時數。
我使用的是SQL Server 2012的
這裏是你能達到你所追求的一種方式,這應該給你足夠讓你的問題開始:
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 |
+-------------+-----------+---------------+----------------+
謝謝,我能夠使用它。它允許我將我的開始和結束時間存儲爲變量,以便我可以使用帶有掩碼的文本框來輸入它們。 – brndnmlk
試試這個:
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
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)
你是如何做的四捨五入?總是上升或下降到下一個30分鐘,或者你是否有一箇中值截止點,其中下方向下取整,上方向上取整? – iamdave