Здравствуйте, Anton Batenev, Вы писали:
AB>Hello, All!
AB>Требуется произвольное значение типа datetime округлить до дня, часа, 10 минут, минуты, отбросив остаток. Например
AB>AB>для значения
AB>01.01.2001 10:11:10.100
AB>округление до дня: 01.01.2001 00:00:00.000
AB>округление до часа: 01.01.2001 10:00:00.000
AB>округление до 10 минут: 01.01.2001 10:10:00.000
AB>округление до минуты: 01.01.2001 10:11:00.000
AB>
AB>Понятно, что тип datetime хранится как 8-и байтовый float, где целая часть — это количество дней с 1900 года. Но вот, что меня смущает:
AB>AB>SET DATEFORMAT DMY
AB>DECLARE @d DATETIME
AB>SET @d = '01.01.2001 10:10:00.000'
AB>SELECT @d, CAST(CAST(@d AS FLOAT) AS DATETIME)
AB>
AB>Результат:
AB>AB>+-------------------------+--------------------------+
AB>| 2001-01-01 10:10:00.000 | 2001-01-01 10:09:59.997 |
AB>+-------------------------+--------------------------+
AB>
AB>1. Чего я неправильно понимаю? Ведь каст между одним и тем же типом не должен приводить к смене значения?
AB>2. Как все же сделать окургление наиболее правильно, при условии, что функция будет использоваться достаточно интенсивно и в больших запросах, и конвертация в символьное представление мне как-то не особо нравится.
?
-- 0 — округлить до дня
-- 1 — округлить до часа
-- 2 — округлить до 10 минут
-- 3 — округлить до минуту
select case @Format
when 0 then dateAdd(hh,-1*DATEPART(hh, @DateTime),dateAdd(mi,-1*DATEPART(mi, @DateTime),dateAdd(ss,-1*DATEPART(ss, @DateTime),dateAdd(ms,-1*DATEPART(ms, @DateTime),@DateTime))))
when 1 then dateAdd(mi,-1*DATEPART(mi, @DateTime),dateAdd(ss,-1*DATEPART(ss, @DateTime),dateAdd(ms,-1*DATEPART(ms, @DateTime),@DateTime)))
when 2 then dateAdd(mi,-1*(DATEPART(mi, @DateTime) — round(DATEPART(mi, @DateTime)-5,-1)),dateAdd(ss,-1*DATEPART(ss, @DateTime),dateAdd(ms,-1*DATEPART(ms, @DateTime),@DateTime)))
when 3 then dateAdd(ss,-1*DATEPART(ss, @DateTime),dateAdd(ms,-1*DATEPART(ms, @DateTime),@DateTime))
end
И оформит как пользовательскую функцию