Saltar al contenido

T-SQL: Redondear al intervalo de 15 minutos más cercano

Si encuentras algún fallo en tu código o proyecto, recuerda probar siempre en un ambiente de testing antes añadir el código al trabajo final.

Solución:

Actualmente estoy usando una variante dateadd/dateiff con una fecha cero (0) para esto. No se requiere fundición:

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

GETDATE() es cualquiera que sea su fecha y hora.

Esto funcionará para fechas al menos hasta el año 5500 antes de que el archivo dateiff falle debido a un desbordamiento. Sin embargo, si intenta usar la segunda precisión, la anterior fallará de inmediato.

El uso de otra fecha fija, como ‘2009-01-01’, o la fecha de hoy (advertencia, SQL más feo) solucionará eso. Una fecha futura también funcionará. Siempre que tenga una parte de tiempo de 00:00:00, puede basar otra fecha y hora en él.

por ejemplo: redondear a los 30 segundos más cercanos:

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

Sé que esta es una publicación antigua, pero quería compartir mi respuesta. Esto se basa en la respuesta de @hbrowser. Esto es lo que se me ocurrió. Esto redondeará hacia arriba o hacia abajo a los 15 minutos más cercanos.

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

Al hacer esta lógica en línea, en lugar de dentro de una función definida por el usuario, en grandes conjuntos de registros debería experimentar un mayor rendimiento.

Puede cambiar la forma en que se produce el redondeo intercambiando el ROUND función a utilizar FLOOR o CAST expr AS INT redondear hacia abajo o usar siempre CEILING para redondear siempre.

Su caso de uso individual determinará qué estilo de redondeo puede necesitar usar.

El siguiente script se puede utilizar para observar las diferencias que ofrecen las distintas técnicas de redondeo:

NOTA: para simplificar la salida, cada resultado se ha convertido a TIME(0), esto solo se hace para simplificar la salida de este ejemplo en particular.

DECLARE @SequenceStart SmallDateTime = CAST(GETDATE() AS Date); 
DECLARE @SequenceEnd SmallDateTime = DateAdd(HOUR, 2, @SequenceStart); -- Recursive CTEs should always have an upper limit
DECLARE @SequenceIntMins INT = 5; -- increment by 5 to show the difference with rounding
WITH TimeSequence([Time]) as
(
    SELECT @SequenceStart as [Time]
    UNION ALL
    SELECT DateAdd(MINUTE, 5, [Time]) FROM TimeSequence 
    WHERE [Time] <= @SequenceEnd
)
    SELECT [Time] = Cast([Time] as TIME(0))
    , Rounded = CAST(DATEADD(MINUTE, ROUND(DATEDIFF(MINUTE, 0, [Time]) / 15.0, 0) * 15, 0) as TIME(0))
    , Casted = CAST(DATEADD(MINUTE, CAST(DATEDIFF(MINUTE, 0, [Time]) / 15.0 AS INT) * 15, 0) as TIME(0))
    , Floored = CAST(DATEADD(MINUTE, FLOOR(DATEDIFF(MINUTE, 0, [Time]) / 15.0) * 15, 0) as TIME(0))
    , Ceilinged = CAST(DATEADD(MINUTE, CEILING(DATEDIFF(MINUTE, 0, [Time]) / 15.0) * 15, 0) as TIME(0))
FROM TimeSequence OPTION ( MaxRecursion 1000);
-- MaxRecursion may be neccessary if you change the interval or end of the sequence
Time        Rounded     Casted      Floored     Ceilinged
00:00:00    00:00:00    00:00:00    00:00:00    00:00:00
00:05:00    00:00:00    00:00:00    00:00:00    00:15:00
00:10:00    00:15:00    00:00:00    00:00:00    00:15:00
00:15:00    00:15:00    00:15:00    00:15:00    00:15:00
00:20:00    00:15:00    00:15:00    00:15:00    00:30:00
00:25:00    00:30:00    00:15:00    00:15:00    00:30:00
00:30:00    00:30:00    00:30:00    00:30:00    00:30:00
00:35:00    00:30:00    00:30:00    00:30:00    00:45:00
00:40:00    00:45:00    00:30:00    00:30:00    00:45:00
00:45:00    00:45:00    00:45:00    00:45:00    00:45:00
00:50:00    00:45:00    00:45:00    00:45:00    01:00:00
00:55:00    01:00:00    00:45:00    00:45:00    01:00:00
01:00:00    01:00:00    01:00:00    01:00:00    01:00:00
01:05:00    01:00:00    01:00:00    01:00:00    01:15:00

Esto fue respondido aquí Cómo redondear una hora en T-SQL y creo que debería funcionar para usted.

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)

Reseñas y valoraciones

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *