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

Sql server 在SQL server数据库中存储时间间隔的最佳方法是什么,sql-server,runtime,Sql Server,Runtime,我有一个要跟踪时间的表,因此有效条目可能是: 1小时3分钟 47分钟 10小时 3分14秒 什么字段类型最适合用于此。很明显我可以用varchar。但我认为可能有更好的方法,因为我希望运行查询来计算多个记录的总时间。不要使用字符类型来存储日期/时间信息 在SQL Server 2008中,您有用于此的时间类型,如果时间间隔小于1天,则应使用该类型。在以前的版本中,或者如果需要存储较大的间隔,则必须使用datetime或smalldatetime(取决于所需的精度) 另一种选择是选择一个时间单

我有一个要跟踪时间的表,因此有效条目可能是:

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

什么字段类型最适合用于此。很明显我可以用varchar。但我认为可能有更好的方法,因为我希望运行查询来计算多个记录的总时间。

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

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


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

只需使用整数以秒为单位存储间隔。返回整数。编写一个函数,将其转换为文本。这一个需要一些调整(所以它显示“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

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


此外,SQL Server 2008引入了一种新的数据类型,允许您仅存储时间值。

正如@Aaronaught所说,使用日期/时间或日期时间(如有必要)数据类型来存储您的值;但这些类型只在时间上存储实例,而不存储时间跨度或持续时间。您需要使用两个字段来存储间隔,例如[time\u span\u start]和[time\u span\u end]。两者之间的差异会给你一个时间间隔

下载Richard T.Snodgrass的“在SQL中开发面向时间的数据库应用程序”一书可以回答您的问题。该文件以PDF格式免费提供,请查看:


与Tony的答案相关,您还可以使用一个datetime列,该列与标准开始时间相对应,该时间对所有时间间隔都是隐式的,例如:1/1/1900 12:00 AM

在这种情况下,存储非常简单:

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等。即,整数被视为自1/1/1900起的天数,小数部分是一天内的分数。所以你可以天真地加上这些来得到一个间隔

事实上:

SELECT  CONVERT(DATETIME, 1) + CONVERT(DATETIME, 0) + CONVERT(DATETIME, 2) + CONVERT(DATETIME, 0.5)
按预期给出“1900-01-04 12:00:00.000”

所以您可以这样做(通过转换来循环求和):

YMMV,我并不是在一般情况下提倡这样做,您选择的任何设计解决方案都应该根据您的所有需求进行验证

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