在SQL Server中将日期时间舍入为最接近的15分钟

bob*_*len 4 sql-server datetime rounding

我在SQL Server中有一个问题与舍入datetime.我进入datetime了专栏rec_datetime,但我想datetime在一个新的列中将r_datetime其舍入,对于整个列,必须舍入到最接近的15分钟rec_datetime.

例:

  • [2015-11-24 19:06:00.000] - 预期结果 - > [2015-11-24 19:00:00.000]
  • [2015-11-24 19:09:00.000] - 预期结果 - > [2015-11-24 19:15:00.000]

是否可以通过选择整列来舍入它?就像是 :

select round(rec_datetime.......
Run Code Online (Sandbox Code Playgroud)

Kev*_*ann 11

圆形,圆形,最近和最接近15分钟

DATEADD( minute, ( DATEDIFF( minute, 0,                                   dateTimeX   ) / 15 ) * 15, 0 ) AS dateTimeRoundDown
DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, dateTimeX ) ) / 15 ) * 15, 0 ) AS dateTimeRoundNearest
DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute,   15           , dateTimeX ) ) / 15 ) * 15, 0 ) AS dateTimeRoundUp  
Run Code Online (Sandbox Code Playgroud)

向下舍入

DATEADD( minute, ( DATEDIFF( minute, 0, dateTimeX ) / 15 ) * 15, 0 ) AS dateTimeRoundDown
Run Code Online (Sandbox Code Playgroud)

以分钟为单位获取偏移量(自基准日期以来的分钟数):

DATEDIFF( minute, 0, dateTimeX )
Run Code Online (Sandbox Code Playgroud)

通过整数除法向下舍入到15分钟:

DATEDIFF( minute, 0, dateTimeX ) / 15 ) * 15
Run Code Online (Sandbox Code Playgroud)

以分钟为单位添加基准日期:

DATEADD( minute, ( DATEDIFF( minute, 0, dateTimeX ) / 15 ) * 15, 0 )
Run Code Online (Sandbox Code Playgroud)

最近的一轮

DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, dateTimeX ) ) / 15 ) * 15, 0 ) AS dateTimeRoundNear
Run Code Online (Sandbox Code Playgroud)

偏移添加15/2分钟.

由于整数除法,需要在几秒钟内完成.

围捕

DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute, 15, dateTimeX ) ) / 15 ) * 15, 0 ) AS dateTimeRoundUp  
Run Code Online (Sandbox Code Playgroud)

偏移量增加了15分钟

基准日期

我通常使用0的基准日期,这是SQL Server的'epoch'

SELECT DATEADD( minute, 0, 0 ) -- '1900-01-01 00:00:00.000'
Run Code Online (Sandbox Code Playgroud)

因为DATEADD()和DATEDIFF()使用SQL Server数据类型INT(32位)作为参数,对于很远的将来的日期,这可能会导致溢出.

使用另一个固定日期,例如'2010-01-01',将避免溢出.

所选基准日期的时间部分必须为00:00:00

使用基数日期和整数除法,不需要转换和不浮点操作.

单元测试

DECLARE @start DATETIME  = '2017-04-20 21:00:00'
DECLARE @end   DATETIME  = '2017-04-20 22: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   ) / 15 ) * 15, 0 ) AS dateTimeRoundDown,
   DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, dateTimeX ) ) / 15 ) * 15, 0 ) AS dateTimeRoundNearest,
   DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( minute,   15           , dateTimeX ) ) / 15 ) * 15, 0 ) AS dateTimeRoundUp

FROM CTE_dateTimes
Run Code Online (Sandbox Code Playgroud)


t-c*_*.dk 2

尝试这样的事情:

SELECT
  dateadd(minute, datediff(minute, '1999-12-31 23:52:30', col) / 15*15, '2000-01-01')
FROM (values('2015-11-24 19:06:00.000'),('2015-11-24 19:09:00.000')) x(col)
Run Code Online (Sandbox Code Playgroud)

结果:

2015-11-24 19:00:00.000
2015-11-24 19:15:00.000
Run Code Online (Sandbox Code Playgroud)