Усреднение значения времени в SQL Sever 2005
-
22-08-2019 - |
Вопрос
У меня есть поле varchar в SQL Sever 2005, в котором хранится значение времени в формате «чч:мм»сс.мммм».
Что я действительно хочу сделать, так это взять среднее значение, используя встроенную агрегатную функцию этих значений времени.Однако это:
SELECT AVG(TimeField) FROM TableWithTimeValues
не работает, поскольку (конечно) SQL не усредняет varchars.Однако это
SELECT AVG(CAST(TimeField as datetime)) FROM TableWithTimeValues
тоже не работает.Насколько я могу судить, SQL не знает, как преобразовать значение только со временем и без даты в поле даты и времени.Я перепробовал множество способов, чтобы заставить SQL преобразовать это поле в поле даты и времени, но пока безуспешно.
Может ли кто-нибудь предложить лучший способ?
Решение
SQL Server может преобразовать часть значения даты и времени, относящуюся только ко времени, из строки в дату и время, однако в вашем примере точность составляет 4 знака после запятой.SQL Server 2005 распознает только 3 места.Поэтому вам нужно будет обрезать самый правый символ:
create table #TableWithTimeValues
(
TimeField varchar(13) not null
)
insert into #TableWithTimeValues
select '04:00:00.0000'
union all
select '05:00:00.0000'
union all
select '06:00:00.0000'
SELECT CAST(TimeField as datetime) FROM #TableWithTimeValues
--Msg 241, Level 16, State 1, Line 1
--Conversion failed when converting datetime from character string.
SELECT CAST(LEFT(TimeField, 12) as datetime) FROM #TableWithTimeValues
--Success!
Это преобразует действительные значения в DATETIME, начиная с 01.01.1900.SQL Server вычисляет даты на основе 1 дня = 1 (целое число).Части дней тогда являются частями значения 1 (т.е.полдень равен 0,5).Поскольку дата не была указана при преобразовании, SQL Server присвоил значение 0 дней (1900-01-01), что соответствует нашей потребности усреднить временной интервал.
Чтобы выполнить операцию AVG для DATETIME, необходимо сначала преобразовать DATETIME в десятичное значение, выполнить агрегирование, а затем выполнить обратное преобразование.Например
SELECT CAST(AVG(CAST(CAST(LEFT(TimeField, 12) as datetime) AS FLOAT)) AS DATETIME) FROM #TableWithTimeValues
--1900-01-01 05:00:00.000
Если вам нужно сохранить это с дополнительным десятичным знаком, вы можете преобразовать DATETIME в VARCHAR только с частью времени и дополнить строку обратно до 13 символов:
SELECT CONVERT(VARCHAR, CAST(AVG(CAST(CAST(LEFT(TimeField, 12) as datetime) AS FLOAT)) AS DATETIME), 114) + '0' FROM #TableWithTimeValues
Другие советы
Попробуй это
AVG(CAST(CAST('1900-01-01 ' + TimeField AS DateTime) AS Float))
В любом случае вам действительно следует хранить их в столбце datetime.Просто используйте для этой части постоянную дату (очень часто встречается 01.01.1900).Тогда вы можете просто вызвать AVG() и не беспокоиться об этом.
Я использовал ответ Cadaeic, чтобы получить ответ, который искал, поэтому решил поделиться кодом....
Я искал запрос, который бы усреднял ВСЕ время, проведенное мной вместе, и давал мне общее время выполнения всех утверждений.Ниже приведен вложенный оператор, который дает вам AVG TAT для отдельных идентификаторов, а при вложении - общий TAT.
SELECT
-- calculates overall TAT for ALL Approvals for specified period of time
-- depending on parameters of query
CONVERT(VARCHAR, CAST(AVG(CAST(CAST(LEFT(Tat_mins, 12) as datetime) AS FLOAT)) AS DATETIME), 108) + '0'
from
(
-- tat is for individual approvals
SELECT
dbo.credit_application.decision_status,
dbo.credit_application.application_id,
cast(dbo.credit_application.data_entry_complete as date) as'Data Entry Date',
cast(dbo.credit_application.decision_date as DATE) as 'Decision Date',
avg(datediff(minute, dbo.credit_application.data_entry_complete, dbo.credit_application.decision_date)) as 'TAT Minutes',
convert (char(5), DateAdd(minute, Datediff(minute,dbo.credit_application.data_entry_complete, dbo.credit_application.decision_date),'00:00:00'),108) as 'TAT_Mins'
FROM dbo.credit_application
where Decision_status not in ('P','N')
group by dbo.credit_application.decision_status,
dbo.credit_application.data_entry_complete,
dbo.credit_application.decision_date
--dbo.credit_application.application_id
)bb
Как вы думаете, как получить среднее значение по дате и времени?
Я предполагаю, что вам нужно ГРУППИРОВАТЬ ПО некоторому периоду (Час?) И отобразить Count (*)?
SQL Server хранит данные даты и времени в виде двух 4-байтовых целых чисел, поэтому дата и время занимают 8 байтов.Первый — это дни с базовой даты, а второй — миллисекунды с полуночи.
Вы можете преобразовать значение даты и времени в целое число и выполнять математические операции, но преобразование возвращает только «дни» значения даты и времени, например.выберите конвертировать(int,getdate()).Сложнее вернуть часть «времени» как целое число.
Подходит ли вам использование SQL Server 2008?В этой версии есть новый выделенный тип данных времени.
Спасибо, Энди.
Я вычислял разницу между всеми датами и произвольной точкой (01.01.1900), усреднял ее, а затем добавлял обратно к произвольной точке.