T-SQL:舍入到最近的15分钟间隔

HH:MM值最接近15分钟的最佳方法是什么? 我不跟踪秒,所以他们无所谓。

00:08:00 becomes 00:15:00 00:07:00 becomes 00:00:00 01:59:00 becomes 02:00:00 

等等。 有没有一个优雅的非UDF或Case语句方法来做到这一点?

编辑:这是我用来获得上述值,我想要整理的SQL:

 CONVERT(CHAR(8), DATEADD(n, SUM(DATEDIFF(n, starttime, stoptime)), 0), 108) 

starttimestoptime是SQL datetime

这是在这里回答如何在T-SQL的时间 ,我认为它应该为你工作。

 CREATE FUNCTION [dbo].[RoundTime] (@Time datetime, @RoundTo float) RETURNS datetime AS BEGIN DECLARE @RoundedTime smalldatetime, @Multiplier float SET @Multiplier = 24.0 / @RoundTo SET @RoundedTime= ROUND(CAST(CAST(CONVERT(varchar, @Time, 121) AS datetime) AS float) * @Multiplier, 0) / @Multiplier RETURN @RoundedTime END -- Usage SELECT dbo.RoundTime('13:15', 0.5) 

我目前正在使用dateadd / datediff变体零(0)date为此。 不需要施法:

 select dateadd(minute, datediff(minute,0,GETDATE()) / 15 * 15, 0) 

GETDATE()是你的date时间。

这会在date之前至less在5500年之前工作,因为溢出。 但是,如果您尝试使用第二个准确性,则上述内容将立即失败。

使用另一个固定的date,如“2009-01-01”或今天的date(警告,更丑陋的SQL)将解决这个问题。 未来的date也将起作用。 只要它有一个00:00:00的时间部分,你可以基于另一个date时间。

例如:轮到最近的30秒:

 select dateadd(second, round(datediff(second, '2010-01-01', GETDATE()) / 30.0, 0) * 30, '2010-01-01'); 

我知道这是一个旧post,但想分享我的答案。 这build立在@hbrowser响应。 这是我想出来的。 这会向上或向下舍入到最接近的15分钟。

 SELECT DATEADD(MINUTE, ROUND(DATEDIFF(MINUTE, 0, GETDATE()) / 15.0, 0) * 15, 0); 

您可以将date四舍五入到最接近的四分之一,如:

 cast(floor(cast(getdate() as float(53))*24*4)/(24*4) as datetime) 

将date时间转换为双精度以避免溢出,double = float(53)。 乘以24 * 4,一天的宿舍数量。 四舍五入到四舍五入的最接近的倍数(),然后除以24 * 4以转换回正常时间。

尝试了Andomar的回答,并在30和00有四舍五入的问题 – 所以一些调整,这完美的作品:

 cast(round(floor(cast(getdate() as float(53))*24*4)/(24*4),5) as smalldatetime) 

这将显示最后15分钟的增量,而不是最近的,即它不会前进,这正是我所需要的。

尝试这个:

 Declare @Dt DateTime Set @Dt = getDate() Select DateAdd(minute, 15 * ((60 * Datepart(hour, @Dt) + Datepart(Minute, @Dt)+ Case When DatePart(second, @Dt) < 30 Then 7 Else 8 End) / 15), DateAdd(day, DateDiff(day, 0, @Dt), 0)) 
 DECLARE @t time ='00:51:00.000' DECLARE @m int = DATEPART(MI,@t)%15 -- 2008 SELECT DATEADD(mi,CASE WHEN @m >=8 THEN 15-@m ELSE -1*@m END,@t) -- 2012 SELECT DATEADD(mi,IIF(@m >=8,15-@m,-1*@m),@t) 

好的最简单的方法:

将分钟数除以60来转换成十进制数。

 8/60 = 0.1333333333333333 

乘以4

 0.1333333333333333 * 4 = 0.5333333333333333 

围绕产品:

 Round(0.5333333333333333,0) = 1 

将整数除以4

 1/4 = 0.25 = 15 minutes 

如果你想分钟乘以60

 0.25*60 = 15 

给一个人一条鱼….

 create function RoundQuarterHour ( @dt datetime ) returns datetime as begin declare @result datetime declare @mm int set @mm=datepart(minute,@dt) set @result = dateadd(minute,-@mm + (round(@mm/cast(15 as float),0)*15) , @dt ) return @result end go select dbo.RoundQuarterHour('2009-may-5 20:00') , '00' union all select dbo.RoundQuarterHour('2009-may-5 20:01') , '01' union all select dbo.RoundQuarterHour('2009-may-5 20:07') , '07' union all select dbo.RoundQuarterHour('2009-may-5 20:08') , '08' union all select dbo.RoundQuarterHour('2009-may-5 20:22') , '22' union all select dbo.RoundQuarterHour('2009-may-5 20:23') , '23' union all select dbo.RoundQuarterHour('2009-may-5 20:37') , '37' union all select dbo.RoundQuarterHour('2009-may-5 20:38') , '38' union all select dbo.RoundQuarterHour('2009-may-5 20:52') , '52' union all select dbo.RoundQuarterHour('2009-may-5 20:53') , '53' union all select dbo.RoundQuarterHour('2009-may-5 20:59') , '59' 

在T-SQL中四舍五入实际上是非常有问题的,而且很多时候是不准确的。

几年前,我把所有的时间都转换成了代码,使用了T-SQL中必须做的所有额外的hub-bub来使它发生并准确地发生。 四舍五入的代码更容易,更准确。

如果您被困在T-SQL中并且没有支持代码,或者没有访问该代码的function,请按照前面提到的示例进行操作。 否则,我虚心推荐让代码做这个工作。

这个怎么样? (为了便于阅读,增加了variables)

 create function dbo.FloorTimeToQuarters ( @dt as datetime ) RETURNS datetime as BEGIN DECLARE @timeAsInt bigint SET @timeAsInt = ( cast( @dt as float ) * 96 ) RETURN DateAdd( hour, @timeAsInt % 96, cast( @timeAsInt / 96 as datetime) ) END 

在15分钟内设置块:

 CREATE FUNCTION RoundQuarterHour ( @dt DATETIME ) RETURNS DATETIME AS BEGIN DECLARE @date DATETIME SET @date = CONVERT(varchar(16),@dt,121) --Sin segundos, ni milisegundos RETURN DATEADD(MINUTE,(DATEPART(MINUTE,@date) % 15)*-1, @date) END PRINT dbo.RoundQuarterHour('2011/01/01 18:00:07') --Jan 1 2011 6:00PM PRINT dbo.RoundQuarterHour('2011/01/01 18:01:07') --Jan 1 2011 6:00PM PRINT dbo.RoundQuarterHour('2011/01/01 18:13:07') --Jan 1 2011 6:00PM PRINT dbo.RoundQuarterHour('2011/01/01 18:14:07') --Jan 1 2011 6:00PM PRINT dbo.RoundQuarterHour('2011/01/01 18:15:07') --Jan 1 2011 6:15PM PRINT dbo.RoundQuarterHour('2011/01/01 18:16:07') --Jan 1 2011 6:15PM 

– 这是我最喜欢的时间

 DECLARE @Time DATETIME = GETDATE() ,@RoundInterval INT = 30 --in minutes, needs to be a number that can be divided evenly into 60 ,@RoundDirection INT = 2 --0 is down to the last interval, 1 is to the nearest interval, 2 is up to the next interval SELECT DATEADD(MINUTE,DATEDIFF(MINUTE,0,DATEADD(SECOND,30*@RoundDirection*@RoundInterval,@Time))/@RoundInterval*@RoundInterval,0) 

这将轮到最接近的15分钟。 您可以将@ROUND修改为您select的时间间隔。

 Declare @Dt DateTime = '2016-01-01 14:38:00' DECLARE @ROUND int = 15; SELECT CASE WHEN (DATEPART(MINUTE, @Dt) % @ROUND) * 60 + DATEPART(SECOND, @Dt) < (30 * @ROUND) THEN DATEADD(minute, datediff(minute,0, @Dt) / @ROUND * @ROUND, 0) ELSE DATEADD(minute, (DATEDIFF(minute,0, @Dt) / @ROUND * @ROUND) + @ROUND, 0) END 

前提分解,找出你想要什么增量,以60分钟的百分比表示,然后计算出需要的增量数量…采取INT值(这会消除余数),在那里你有它是一个简单的函数向上或向下舍入到最近的增量。

简单的function:

  ALTER FUNCTION [dbo].[RoundOffDateTime] ( @IncDate DATETIME, @Increment INT ) RETURNS SMALLDATETIME AS BEGIN DECLARE @IncrementPercent DECIMAL(2,2) = CAST(@Increment as decimal)/60 DECLARE @IncMinutes REAL = ROUND(CAST(DATEPART(mi,@IncDate) as decimal)/CAST(@Increment as decimal),0) DECLARE @MinutesNeeded INT = CAST(@IncMinutes * @Increment as INT) RETURN CAST(DATEADD(mi,@MinutesNeeded,DATEADD(ss,-DATEPART(ss,@IncDate),DATEADD(mi,-DATEPART(mi,@IncDate),@IncDate))) as smalldatetime) END