我有一个表,我想在其中跟踪时间,因此有效条目可能是:
最适合使用哪种字段类型。 我显然可以使用 varchar 。 .但我认为可能有更好的东西,因为我想运行查询来计算多条记录的总时间。
不要使用字符类型来存储日期/时间信息。
在 SQL Server 2008 中,您可以使用time
类型来实现此目的,如果您的时间间隔小于 1 天,则应该使用该类型。 在以前的版本中,或者如果您需要存储更大的间隔,则必须使用
datetime
或
smalldatetime
(取决于您需要的精度)。另一种选择是选择一个时间单位(例如分钟),然后使用
int
值来表示单位数。 只需确保 (a) 您选择的单位实际上足够精确,可以记录您需要跟踪的最小间隔,并且 (b) 实际数字类型足够大,可以容纳您需要跟踪的最大间隔。
smallint
可能足以追踪一天内的分钟数;另一方面,跟踪 10 年时间范围内的毫秒数必须存储为
bigint
。
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
time_span_start
和time_span_end
。两者之间的差异将为您提供间隔。
可以通过下载 Richard T. Snodgrass 所著的《用 SQL 开发面向时间的数据库应用程序》副本来获得您问题的非常详细的答案。它以 PDF 形式免费提供,请查看此处:
http://www.cs.arizona.edu/~rts/publications.html
取决于您的时间范围 - 要么将所有内容转换为秒,然后将该值存储为 INT,或者如果您的时间跨度较大,您可能需要分别使用小时、分钟、秒字段。TIME
数据类型,它允许您存储仅时间值。
与托尼的回答相关,您还可以使用相对于所有间隔隐含的标准开始时间的单个日期时间列 - 例如: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 等,即整数被视为自 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,您选择的任何设计解决方案都应该根据您的所有要求进行验证。