我需要将datetime2值向下舍入到最近的半小时。例如'10 / 17/2013 12:10:00.123'将向下舍入到'10 / 17/2013 12:00:00.0'和'10 / 17/2013 12:34:17.123'将向下舍入到10/17 / 2013 12:30:00.0'。我的第一个想法是创建一个UDF,它可以打破日期和时间,并以这种方式进行。但是,我想知道这样的事情是否可以在单个T-SQL语句中完成?
我正在使用SQL Server 2012,该列的数据类型是dateTime2(无法转换为float !!)
答案 0 :(得分:11)
Ian的答案很好,但它包含了不必要的转换。我建议
SELECT CONVERT(smalldatetime, ROUND(CAST([columnname] AS float) * 48.0,0,1)/48.0) FROM [tableName]
如果要舍入到最近的半小时而不是总是向下舍入,请使用
SELECT CONVERT(smalldatetime, ROUND(CAST([columnname] AS float) * 48.0,0)/48.0) FROM [tableName]
答案 1 :(得分:1)
这个怎么样
declare @d datetime = '2013-05-06 12:29.123'
select
case
when datepart(minute, @d) < 30 then cast(dateadd(minute, -datepart(minute,@d)-datepart(second,@d), @d) as smalldatetime)
when datepart(minute, @d) >= 30 then cast(dateadd(minute, -datepart(minute,@d)-datepart(second,@d)+30, @d) as smalldatetime)
end
答案 2 :(得分:0)
select cast(floor(cast(
cast('10/17/2013 12:34:00' as datetime)
as float(53)) * 48) / 48 as datetime)
修改强>
如果使用smalldatetime来避免额外的精度,那么效果会更好
select cast(floor(cast(
cast('2012-01-02 11:33:14.097' as smalldatetime)
as float(53)) * 48) / 48 as smalldatetime)
答案 3 :(得分:0)
这是一种方法:
update t set
d = dateadd(minute,datediff(minute,'19000101',d)/30*30,'19000101');
答案 4 :(得分:0)
当我需要向下舍入到最接近的5分钟间隔时,我使用的方法略有不同。可能有一种方法可以进一步简化这一点,但至少这让我得到了我需要的东西。
DECLARE @now datetime = GETDATE()
SELECT @now as cur_datetime, DATEADD(MINUTE, -(DATEDIFF(MINUTE,DATEADD(HOUR,DATEDIFF(HOUR,0,@now), 0),DATEADD(MINUTE,DATEDIFF(MINUTE,0,@now), 0)) % 5), DATEADD(MINUTE,DATEDIFF(MINUTE,0,@now), 0)) as round_down_to_nearest_5_minute_mark
答案 5 :(得分:0)
@Twinkles的答案在SQL Server中效果很好,可以将其舍入到最接近的半小时。
但是,在开发中,强烈建议使用FLOOR舍入到 最后半小时 。
SELECT CONVERT(datetime, FLOOR(CAST([columnname] AS float) * 48.0)/48.0) FROM [tableName]
答案 6 :(得分:0)
您可以使用 DATETIME2FROMPARTS
来重建日期。要将分钟向下四舍五入到 30 分钟间隔,请使用公式 minutes intdiv 30 * 30
SELECT
dt2,
DATETIME2FROMPARTS(
DATEPART(year, dt2),
DATEPART(month, dt2),
DATEPART(day, dt2),
DATEPART(hour, dt2),
DATEPART(minute, dt2) / 30 * 30,
0,
0,
0
)
FROM (VALUES
-- generic datetime2
(SYSDATETIME()),
-- 30 minute boundary
('2001-01-01 00:29:59.9999999'),
('2001-01-01 00:30:00.0000000'),
('2001-01-01 00:30:00.0000001'),
-- min and max date
('0001-01-01 00:00:00.0000000'),
('9999-12-31 23:59:59.9999999')
) AS v(dt2)