哪个舍入舍入日期时间在 SQL 中更有效
Posted
技术标签:
【中文标题】哪个舍入舍入日期时间在 SQL 中更有效【英文标题】:which rounding rounding datetime is more efficient in SQL 【发布时间】:2021-01-13 08:50:48 【问题描述】:我将编写一个对日期时间值进行舍入的代码,但我无法比较哪个更有效:
DECLARE @DateValue DATETIME = '2021-01-13 11:59:59'
---- FIRST SOLUSTION:
SELECT CAST(@DateValue AS smalldatetime) AS DateRoundS1
---- SECOND SOLUTION:
SELECT CONVERT(smalldatetime, @DateValue) AS DateRoundS2
---- THIRD SOLUTION:
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, @DateValue), 0) AS DateRoundS3
---- FORTH SOLUTION:
DECLARE @DateValue DATETIME = '2021-01-13 11:59:59'
DECLARE @DiffMinsTime INT = DATEPART(MINUTE,@DateValue)
DECLARE @DiffSecsTime INT = DATEPART(SECOND,@DateValue)
DECLARE @DiffMSTime INT = DATEPART(MILLISECOND,@DateValue)
IF( @DiffMinsTime > 0 )
BEGIN
SELECT DATEADD(MINUTE,DATEDIFF(MINUTE,@DiffMinsTime,@DateValue),0)
END
IF(@DiffSecsTime > 0)
BEGIN
SELECT DATEADD(SECOND,DATEDIFF(SECOND,@DiffSecsTime,@DateValue),0)
END
IF(@DiffMSTime > 0)
BEGIN
SELECT DATEADD(MILLISECOND,DATEDIFF(MILLISECOND,@DiffMSTime,@DateValue),0)
END
PS:我知道最后一个溢出了!! 有没有更有效的方法来做到这一点?!
【问题讨论】:
什么是“高效”?正在尝试转换数百万行?告诉我们一些背景信息! 但是CAST
和CONVERT
非常快,但许多日期和时间函数也是如此(例如DATEADD
和DATEDIFF
)。你想把时间“圆”到这里吗?
Tip1 - 使用 DATETIME2
1 & 2 完全相同,CAST
只是调用CONVERT
。 3也会很快。 4 看起来很慢。我通常做CAST(@DateValue AS date)
除了cast()
/convert()
之外,你为什么会考虑使用other?
【参考方案1】:
对于转换和转换,它总是取决于很多因素。 最好的方法:建立一个测试台,并留出几分钟或更长时间。
测试台创建从 0 到 9 999 999 的数字 - 大约 1000 万行。感谢 Jeff Moden 创建数字列表的 SQL spackle。
DROP TABLE IF EXISTS #numbers
;
DROP TABLE IF EXISTS #dates
;
CREATE TABLE
#numbers
(
number integer NOT NULL
)
;
CREATE TABLE
#dates
(
dated datetime2(7) NOT NULL
)
;
WITH
cteNum
(
smallnum
)
AS
(
SELECT Cast( 1 AS integer )
UNION ALL
SELECT Cast( 2 AS integer )
UNION ALL
SELECT Cast( 3 AS integer )
UNION ALL
SELECT Cast( 4 AS integer )
UNION ALL
SELECT Cast( 5 AS integer )
UNION ALL
SELECT Cast( 6 AS integer )
UNION ALL
SELECT Cast( 7 AS integer )
UNION ALL
SELECT Cast( 8 AS integer )
UNION ALL
SELECT Cast( 9 AS integer )
UNION ALL
SELECT Cast( 0 AS integer )
)
INSERT INTO
#numbers
(
number
)
SELECT
num1.smallnum * 1000000 + num2.smallnum * 100000 + num3.smallnum * 10000 + num4.smallnum * 1000
+ num5.smallnum * 100 + num6.smallnum * 10 + num7.smallnum
FROM
cteNum AS num1
CROSS JOIN cteNum AS num2
CROSS JOIN cteNum AS num3
CROSS JOIN cteNum AS num4
CROSS JOIN cteNum AS num5
CROSS JOIN cteNum AS num6
CROSS JOIN cteNum AS num7
;
INSERT INTO
#dates
(
dated
)
SELECT
Cast( DateAdd( ms, nums.number, dated.basedate) AS datetime2(7) ) AS dated
FROM
#numbers AS nums
CROSS JOIN
(
SELECT Cast(GetDate() AS datetime2(7) ) AS basedate
) dated
;
DROP TABLE IF EXISTS #numbers
;
这将需要几秒钟到几分钟的时间来创建。 使用表可以最大限度地减少查询分析器对表进行维护的工作量。
然后可以在受控环境中进行转换时间测试。提示:使用开始和结束时间捕获可以消除 SQL 跟踪的开销。
SET NOCOUNT ON
;
DECLARE
@datetimestarted datetime2(7),
@datetimeended datetime2(7),
@result varchar(200),
@crlf char(2) = char(13) + char(10)
;
SET @datetimestarted = Getdate()
;
SELECT
dated,
datedrounded = Cast( dated AS datetime2(0) )
FROM
#dates
;
SET @datetimeended = Getdate()
;
SET @result = 'Processing time = ' + Cast( Datediff( ms, @datetimestarted, @datetimeended ) / 1000 AS varchar(12) ) + ' seconds' + @crlf
+ ' > Start time: ' + Convert( varchar(20), @datetimestarted, 126 ) + @crlf
+ ' > End time: ' + Convert( varchar(20), @datetimeended, 126 ) + @crlf
;
PRINT @result
;
SET @datetimestarted = Getdate()
;
SELECT
dated,
datedrounded = Convert( datetime2(0), dated )
FROM
#dates
;
SET @datetimeended = Getdate()
;
SET @result = 'Processing time = ' + Cast( Datediff( ms, @datetimestarted, @datetimeended ) / 1000 AS varchar(12) ) + ' seconds' + @crlf
+ ' > Start time: ' + Convert( varchar(20), @datetimestarted, 126 ) + @crlf
+ ' > End time: ' + Convert( varchar(20), @datetimeended, 126 ) + @crlf
;
PRINT @result
;
每个选项在我的 VM 上的运行时间约为 3 分钟,其中 Cast 比 Convert 稍微长一点。现在这取决于人们想要实现的目标,因此请随意根据需要更改转换。
最后是清理。
DROP TABLE IF EXISTS #dates
;
最后提示:日期和日期时间是 SQL Server 中过时的日期时间类型。使用这些进行计算实际上比允许数学计算的新 datetime2 类型更容易。
datetime2 需要使用 Dateadd 函数。 但是 datetime2 更容易转换为不同类型的 RDBMS 之间的当前数据库交互。还更容易以标准 ISO 8601 格式工作,这使得在世界不同地区之间传输数据变得更加容易。
【讨论】:
以上是关于哪个舍入舍入日期时间在 SQL 中更有效的主要内容,如果未能解决你的问题,请参考以下文章
SimpleDateFormat 不解析毫秒,MySql 正在舍入日期