Date / heure T-SQL arrondie à la minute la plus proche et aux heures les plus proches avec l'utilisation des fonctions

113

Dans SQL Server 2008, je voudrais obtenir la colonne datetime arrondie à l'heure la plus proche et à la minute la plus proche de préférence avec les fonctions existantes en 2008.

Pour cette valeur de colonne 2007-09-22 15:07:38.850, la sortie ressemblera à ceci :

2007-09-22 15:08 -- nearest minute
2007-09-22 15    -- nearest hour
user219628
la source
6
L'exemple de minute le plus proche ne devrait-il pas être 15:08? Parce que les secondes dans une minute font 60 ...
OMG Ponies
N'avez-vous pas corrigé cette erreur intentionnellement lorsque vous avez modifié sa question pour pouvoir faire ce commentaire?
Mr mercredi
@MrWednesday Vous réalisez qu'il y a plus de 10 minutes entre l'édition et ce commentaire. J'imagine que la pensée s'est produite après.
lc.

Réponses:

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)

reviendra

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

Ce qui précède ne fait que tronquer les secondes et les minutes, produisant les résultats demandés dans la question. Comme @OMG Ponies l'a souligné, si vous voulez arrondir vers le haut / bas, vous pouvez ajouter respectivement une demi-minute ou une demi-heure, puis tronquer:

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

et vous obtiendrez:

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

Avant l' ajout du type de données de date dans SQL Server 2008, j'utiliserais la méthode ci-dessus pour tronquer la partie temporelle d'une date / heure pour obtenir uniquement la date. L'idée est de déterminer le nombre de jours entre la date et l'heure en question et un point fixe dans le temps ( 0, qui se convertit implicitement en 1900-01-01 00:00:00.000):

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

puis ajoutez ce nombre de jours au point fixe dans le temps, ce qui vous donne la date d'origine avec l'heure définie sur 00:00:00.000:

select dateadd(day, @days, 0)

ou plus succinctement:

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

L'utilisation d'une autre datepart (par exemple hour, mi) fonctionnera en conséquence.

Jeff Ogata
la source
2
Je doute que quelqu'un d'autre se heurte à cela, mais si vous essayez d'arrondir à la seconde la plus proche et d'ajouter 500 millisecondes, vous voudrez faire datéiff (deuxième, '1/1/2000', .... vs datéiff (deuxième, 0 ... car vous obtiendrez une erreur de dépassement de capacité. secondes à partir de 0 est trop grand, je suppose.
Eric Twilegar
'Ajoutez le nombre d'heures depuis le 1er janvier 1900 au 1er janvier 1900' - J'ai rencontré cela en Java / SQL, où cela a l'air moche. Dans mon cas, cela aurait vraiment dû être fait du côté Java.
Corwin Newall
Pour les calculs avec datetimeoffset, j'ai dû remplacer 0par TODATETIMEOFFSET('1900-01-01 00:00:00', 0)pour éviter de forcer le fuseau horaire local sur le résultat.
krlmlr
26

"Arrondi" comme dans votre exemple. Cela renverra une valeur varchar de la date.

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
la source
Convertir le varchar en datetime pourrait faire (pendant une heure):CONVERT(datetime, CONVERT(VARCHAR(13), @date, 120)+':00:00')
Decula
10

Je me rends compte que cette question est ancienne et qu'il existe une réponse acceptée et alternative. Je me rends également compte que ma réponse ne répondra qu'à la moitié de la question, mais pour quiconque souhaite arrondir à la minute la plus proche et avoir toujours une valeur compatible datetime en utilisant une seule fonction :

CAST(YourValueHere as smalldatetime);

Pendant des heures ou des secondes, utilisez la réponse de Jeff Ogata (la réponse acceptée) ci-dessus.

Andrew Steitz
la source
1
Excellente réponse, j'ai vérifié que ça arrondit et pas seulement tronque. Pour tous ceux qui recherchent cette option, a smalldatetimeété ajoutée dans SQL 2008.
BradC
C'est la meilleure option si vous avez besoin de corriger certaines données de votre table qui ne nécessitent qu'un délai à la minute.
Chiffrement
-1

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

arrondira les secondes à 00

Jam_Jam
la source
Très lent, et n'arrondit pas comme le PO l'a demandé, mais arrondit vers le bas, ce qu'il n'a pas demandé. (Avertissement - Je n'ai pas voté contre vous)
Ingénieur inversé