Вопрос

У меня есть поле 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), усреднял ее, а затем добавлял обратно к произвольной точке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top