что лучший способ состоит в том, чтобы сохранить временной интервал в базе данных SQL-сервера

у меня есть таблица, где я хочу отследить время, таким образом, действительный доступ мог бы быть:

  • 1 час 3 минуты
  • 47 минут
  • 10 часов
  • 3 минуты 14 секунд

какой тип поля лучше всего используется для этого. я, очевидно, мог использовать varchar. .but, я думал, что могло бы быть что-то лучше, поскольку я хотел бы к выполнению запросов составить количество времени по многим записям.

10
задан leora 7 March 2010 в 19:15
поделиться

5 ответов

Не не используйте типы символов для хранения информации о дате / времени.

В SQL Server 2008 для этого используется тип time , который следует использовать, если ваши временные интервалы меньше 1 дня. В предыдущих версиях или если вам нужно хранить большие интервалы, вам придется использовать datetime или smalldatetime (в зависимости от необходимой точности).

Другой вариант - выбрать единицу времени - скажем, минуты - и просто использовать значение int для представления количества единиц. Просто убедитесь, что (а) выбранная вами единица измерения действительно достаточно точна, чтобы записывать наименьшие интервалы, которые вам нужно отслеживать, и (б) фактический числовой тип достаточно велик, чтобы содержать наибольшие интервалы, которые вам нужно отслеживать. smallint может быть достаточным для отслеживания количества минут в течение дня; с другой стороны, отслеживание количества миллисекунд в течение 10-летнего периода должно быть сохранено как bigint .

13
ответ дан 3 December 2019 в 17:58
поделиться

В связи с ответом Тони, вы также можете использовать один столбец времени даты относительно стандартного времени начала, которое является неявным для всех интервалов - например: 1/1/1900 12:00 AM.

В этом случае это достаточно просто для хранения:

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

Теперь это не совсем просто для выполнения SUMs строк, поэтому можно подумать о добавлении сохраняемого вычисляемого столбца(ов) DATEDIFF(s, '1/1/1900', interval) для обеспечения секунд для выполнения SUMs.

Теперь, вот где становится интересно для 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', как и ожидалось

Так что вы можете сделать это (обойти 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, и любое решение, которое вы выберете, должно быть проверено на соответствие всем вашим требованиям.

0
ответ дан 3 December 2019 в 17:58
поделиться

Просто используйте целое число, чтобы сохранить интервал в секундах. 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
ответ дан 3 December 2019 в 17:58
поделиться

Зависит от вашего диапазона времени - либо конвертируйте все в секунд и просто сохраните это значение как INT, или, если ваш промежуток времени больше, вы можете использовать поля для часов, минут, секунд отдельно.

Кроме того, SQL Server 2008 представляет новый тип данных TIME , который позволяет хранить только временные значения.

2
ответ дан 3 December 2019 в 17:58
поделиться

Как сказал @Aaronaught, используйте тип данных date / time или datetime (при необходимости) для хранения ваших значений; но эти типы хранят только экземпляр во времени, а не промежуток времени или продолжительность. Вам нужно будет использовать два поля для хранения интервала, например. [time_span_start] и [time_span_end]. Разница между ними даст вам интервал.

На более подробный ответ на ваш вопрос можно ответить, загрузив копию книги Ричарда Т. Снодграсса «Разработка приложений для баз данных, ориентированных по времени на SQL». Он находится в свободном доступе в формате PDF, посмотрите здесь:

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

2
ответ дан 3 December 2019 в 17:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: