Data e hora do T-SQL arredondada para o minuto mais próximo e as horas mais próximas com o uso de funções

113

No SQL server 2008, gostaria que a coluna datetime fosse arredondada para a hora e o minuto mais próximos, de preferência com as funções existentes em 2008.

Para este valor de coluna 2007-09-22 15:07:38.850, a saída será semelhante a:

2007-09-22 15:08 -- nearest minute
2007-09-22 15    -- nearest hour
user219628
fonte
6
O exemplo do minuto mais próximo não deveria ser 15:08? Porque segundos em um minuto são 60 ...
Pôneis OMG
Você intencionalmente não corrigiu esse erro ao editar a pergunta dele para poder fazer aquele comentário?
Sr. Quarta-feira
@MrWed Wednesday Você sabe que há mais de 10 minutos entre a edição e aquele comentário. Eu imagino que o pensamento ocorreu depois.
lc.

Respostas:

208
declare @dt datetime

set @dt = '09-22-2007 15:07:38.850'

select dateadd(mi, datediff(mi, 0, @dt), 0)
select dateadd(hour, datediff(hour, 0, @dt), 0)

retornará

2007-09-22 15:07:00.000
2007-09-22 15:00:00.000

O anterior apenas trunca os segundos e minutos, produzindo os resultados solicitados na pergunta. Como @OMG Ponies apontou, se você quiser arredondar para cima / para baixo, pode adicionar meio minuto ou meia hora respectivamente e, em seguida, truncar:

select dateadd(mi, datediff(mi, 0, dateadd(s, 30, @dt)), 0)
select dateadd(hour, datediff(hour, 0, dateadd(mi, 30, @dt)), 0)

e você obterá:

2007-09-22 15:08:00.000
2007-09-22 15:00:00.000

Antes de o tipo de dados de data ser adicionado ao SQL Server 2008, eu usaria o método acima para truncar a parte do tempo de uma data e hora para obter apenas a data. A ideia é determinar o número de dias entre a data e hora em questão e um ponto fixo no tempo ( 0que implicitamente converte para 1900-01-01 00:00:00.000):

declare @days int
set @days = datediff(day, 0, @dt)

e, em seguida, adicione esse número de dias ao ponto fixo no tempo, o que fornece a data original com a hora definida para 00:00:00.000:

select dateadd(day, @days, 0)

ou mais sucintamente:

select dateadd(day, datediff(day, 0, @dt), 0)

Usar uma parte da data diferente (por exemplo hour, mi) funcionará de acordo.

Jeff Ogata
fonte
2
Duvido que alguém mais se depare com isso, mas se você está tentando arredondar PARA CIMA para o segundo mais próximo e adicionar 500 milissegundos, você vai querer fazer datediff (segundo, '1/1/2000', .... vs datediff (segundo, 0 .... pois você obterá um erro de estouro. segundos de 0 é muito grande, eu acho.
Eric Twilegar
'Some o número de horas desde 1º de janeiro de 1900 a 1º de janeiro de 1900' - encontrei isso em Java / SQL, onde parece feio. No meu caso, realmente deveria ter sido feito no lado Java.
Corwin Newall
Para cálculos com datetimeoffset, tive que substituir 0por TODATETIMEOFFSET('1900-01-01 00:00:00', 0)para evitar forçar o fuso horário local no resultado.
krlmlr
26

"Arredondado" para baixo como no seu exemplo. Isso retornará um valor varchar da data.

DECLARE @date As DateTime2
SET @date = '2007-09-22 15:07:38.850'

SELECT CONVERT(VARCHAR(16), @date, 120) --2007-09-22 15:07
SELECT CONVERT(VARCHAR(13), @date, 120) --2007-09-22 15
Magnus
fonte
Converter o varchar de volta em data e hora poderia fazer (por hora):CONVERT(datetime, CONVERT(VARCHAR(13), @date, 120)+':00:00')
Decula
10

Sei que essa pergunta é antiga e há uma resposta aceita e outra alternativa. Também percebo que minha resposta responderá apenas metade da pergunta, mas para quem deseja arredondar para o minuto mais próximo e ainda tem um valor compatível com data e hora usando apenas uma única função :

CAST(YourValueHere as smalldatetime);

Por horas ou segundos, use a resposta de Jeff Ogata (a resposta aceita) acima.

Andrew Steitz
fonte
1
Excelente resposta, verifiquei que é arredondado e não apenas truncado. Para qualquer pessoa que esteja procurando por essa opção, smalldatetimefoi adicionado no SQL 2008.
BradC
Esta é a melhor opção se você precisar corrigir alguns dados em sua tabela que exigem apenas um minuto.
Criptografia de
-1

Select convert(char(8), DATEADD(MINUTE, DATEDIFF(MINUTE, 0, getdate), 0), 108) as Time

irá arredondar os segundos para 00

Jam_Jam
fonte
Muito lento, e não termina como o OP pediu, mas arredondou para baixo, pelo que ele não pediu. (Isenção de responsabilidade - eu não votei contra você)
Inverteu o engenheiro em