在 SQL Server 数据库中存储时间间隔的最佳方法是什么

问题描述 投票:0回答:5

我有一个表,我想在其中跟踪时间,因此有效条目可能是:

  • 1小时3分钟
  • 47分钟
  • 10小时
  • 3分14秒

最适合使用哪种字段类型。 我显然可以使用 varchar 。 .但我认为可能有更好的东西,因为我想运行查询来计算多条记录的总时间。

sql-server runtime
5个回答
16
投票

不要使用字符类型来存储日期/时间信息。

在 SQL Server 2008 中,您可以使用

time

 类型来实现此目的,如果您的时间间隔小于 1 天,则应该使用该类型。  在以前的版本中,或者如果您需要存储更大的间隔,则必须使用
datetime
smalldatetime
(取决于您需要的精度)。

另一种选择是选择一个时间单位(例如分钟),然后使用

int

 值来表示单位数。  只需确保 (a) 您选择的单位实际上足够精确,可以记录您需要跟踪的最小间隔,并且 (b) 实际数字类型足够大,可以容纳您需要跟踪的最大间隔。  
smallint
 可能足以追踪一天内的分钟数;另一方面,跟踪 10 年时间范围内的毫秒数必须存储为 
bigint


5
投票
只需使用整数来存储间隔(以秒为单位)。

DATEDIFF 返回整数。编写一个将其转换为文本的函数。这个需要一些调整(所以它显示“1 分钟”,而不是“1 分钟”),但应该可以正常工作:

CREATE FUNCTION dbo.SecondsToText(@seconds int) RETURNS VARCHAR(100) AS BEGIN declare @days int; set @days = @seconds/(3600 * 24); declare @hours int; set @hours = (@seconds - @days * 3600 * 24) / 3600; declare @minutes int; set @minutes = (@seconds - @days * 3600 * 24 - @hours * 3600) / 60; set @seconds = (@seconds - @days * 3600 * 24 - @hours * 3600 - @minutes * 60); RETURN RTRIM(CASE WHEN @days > 0 THEN CAST(@days as varchar) + ' days ' ELSE '' END + CASE WHEN @hours > 0 THEN CAST(@hours as varchar) + ' hours ' ELSE '' END + CASE WHEN @minutes > 0 THEN CAST(@minutes as varchar) + ' minutes ' ELSE '' END + CASE WHEN @seconds > 0 THEN CAST(@seconds as varchar) + ' seconds ' ELSE '' END) END GO
    

5
投票
正如@Aaronaught所说,使用日期/时间或日期时间(根据需要)数据类型来存储您的值;但这些类型仅存储时间上的“实例”,而不是时间跨度或持续时间。您将需要使用两个字段来存储间隔,例如

time_span_starttime_span_end

。两者之间的差异将为您提供间隔。
可以通过下载 Richard T. Snodgrass 所著的《用 SQL 开发面向时间的数据库应用程序》副本来获得您问题的非常详细的答案。它以 PDF 形式免费提供,请查看此处:

http://www.cs.arizona.edu/~rts/publications.html

取决于您的时间范围 - 要么将所有内容转换为秒,然后将该值存储为 INT,或者如果您的时间跨度较大,您可能需要分别使用小时、分钟、秒字段。

2
投票
此外,SQL Server 2008 还引入了新的

TIME

数据类型,它允许您存储仅时间值。

    

与托尼的回答相关,您还可以使用相对于所有间隔隐含的标准开始时间的单个日期时间列 - 例如:1/1/1900 12:00 AM。

0
投票
在这种情况下,存储起来很容易:

INSERT INTO tbl (interval) VALUES (DATEADD(s, '1/1/1900', DATEDIFF(s, @starttime, @endtime))

现在对行进行求和显然并不容易,因此您可以考虑添加 DATEDIFF(s, '1/1/1900', Interval) 的持久计算列以提供执行求和的秒数。

现在,这就是 SQL Server 有趣的地方:

由于 SQL Server 实现了数字与日期之间的转换,0 -> 1/1/1900 12:00 AM、0.5 -> 1/1/1900 12:00 PM、1 -> 1/2/1900 12: 00 AM 等,即整数被视为自 1900 年 1 月 1 日以来的天数,小数部分为当天内的分数。 所以你实际上可以天真地添加这些来获得一个间隔。

事实上:

SELECT CONVERT(DATETIME, 1) + CONVERT(DATETIME, 0) + CONVERT(DATETIME, 2) + CONVERT(DATETIME, 0.5)

按预期给出 '1900-01-04 12:00:00.000'

所以你可以这样做(通过转换绕过 SUM):

DECLARE @datetest TABLE ( dt DATETIME NOT NULL ) INSERT INTO @datetest ( dt ) VALUES ( 0 ) INSERT INTO @datetest ( dt ) VALUES ( 1 ) INSERT INTO @datetest ( dt ) VALUES ( 2 ) INSERT INTO @datetest ( dt ) VALUES ( 0.5 ) SELECT * FROM @datetest SELECT CONVERT(DATETIME, SUM(CONVERT(FLOAT, dt))) FROM @datetest

我并不提倡这样做,YMMV,您选择的任何设计解决方案都应该根据您的所有要求进行验证。
    

© www.soinside.com 2019 - 2024. All rights reserved.