Dze*_*jms 45 sql sql-server datetime
将HH:MM值舍入到最接近的15分钟间隔的最佳方法是什么?我不追踪秒,所以他们无关紧要.
00:08:00 becomes 00:15:00
00:07:00 becomes 00:00:00
01:59:00 becomes 02:00:00
Run Code Online (Sandbox Code Playgroud)
等等.这样做是否有优雅的非UDF或Case语句方法?
编辑:这是我用来获取我想要舍入的上述值的SQL:
CONVERT(CHAR(8), DATEADD(n, SUM(DATEDIFF(n, starttime, stoptime)), 0), 108)
Run Code Online (Sandbox Code Playgroud)
starttime并且stoptime是SQL datetime.
小智 64
我目前正在使用dateadd/datediff变体,其日期为零(0).不需要铸造:
select dateadd(minute, datediff(minute,0,GETDATE()) / 15 * 15, 0)
Run Code Online (Sandbox Code Playgroud)
GETDATE()是您的日期时间.
这将适用于日期至少5500年之前的日期,因为溢出会导致日期失效.但是,如果您尝试使用第二个精度,则上面会立即失败.
使用另一个固定日期,如'2009-01-01',或今天的日期(警告,更丑陋的SQL)将解决这个问题.未来的日期也将有效.只要它的时间部分为00:00:00,您就可以在其上建立另一个日期时间.
例如:舍入到最近的30秒:
select dateadd(second, round(datediff(second, '2010-01-01', GETDATE()) / 30.0, 0) * 30, '2010-01-01');
Run Code Online (Sandbox Code Playgroud)
u07*_*7ch 27
这里回答了如何在T-SQL中完成一段时间,我认为它应该对你有用.
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)
Run Code Online (Sandbox Code Playgroud)
小智 25
我知道这是一个老帖子,但想分享我的答案.这建立在@hbrowser响应的基础上.这就是我想出来的.这将向上或向下舍入到最近的15分钟.
SELECT DATEADD(MINUTE, ROUND(DATEDIFF(MINUTE, 0, GETDATE()) / 15.0, 0) * 15, 0);
Run Code Online (Sandbox Code Playgroud)
通过内联而不是在用户定义的函数内部执行此逻辑,在大型记录集上,您应该体验更高的性能.
您可以通过交换
ROUND要使用的功能FLOOR或CAST expr AS INT始终向下舍入或使用CEILING始终向上舍入来更改舍入方式.
您的个人用例将决定您可能需要使用哪种舍入方式.
以下脚本可用于观察不同舍入技术提供的差异:
注意:为了简化输出,每个结果都已转换为TIME(0),这只是为了简化此特定示例的输出.
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
Run Code Online (Sandbox Code Playgroud)
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
您可以将日期舍入到最近的区域,如:
cast(floor(cast(getdate() as float(53))*24*4)/(24*4) as datetime)
Run Code Online (Sandbox Code Playgroud)
将datetime转换为double precesion以避免溢出,double = float(53).乘以24*4,即一天中的季度数.使用floor()舍入到最接近的四分之一倍数,然后除以24*4以转换回正常时间.
小智 5
尝试了Andomar的答案,在30和00时出现了四舍五入的问题-进行了一些调整,效果很好:
cast(round(floor(cast(getdate() as float(53))*24*4)/(24*4),5) as smalldatetime)
Run Code Online (Sandbox Code Playgroud)
这将显示最后15分钟的增量,而不是最近的增量,即它不会向前移动,这正是我所需要的。
| 归档时间: |
|
| 查看次数: |
81073 次 |
| 最近记录: |