Среднее значение времени в SQL Sever 2005 - PullRequest
3 голосов
/ 09 февраля 2009

В SQL Sever 2005 у меня есть поле varchar, в котором хранится значение времени в формате "чч: мм" сс.мммм ".

Что я действительно хочу сделать, так это взять среднее значение, используя встроенную функцию агрегирования этих значений времени. Однако это:

SELECT AVG(TimeField) FROM TableWithTimeValues

не работает, так как (конечно) SQL не будет усреднять varchars. Тем не менее, это

SELECT AVG(CAST(TimeField as datetime)) FROM TableWithTimeValues

также не работает. Насколько я могу судить, SQL не знает, как преобразовать значение только с указанием времени и без даты в поле datetime. Я пробовал множество вещей, чтобы заставить SQL превратить это поле в дату и время, но пока что не повезло.

Кто-нибудь может предложить лучший способ?

Ответы [ 6 ]

7 голосов
/ 10 февраля 2009

SQL Server может преобразовывать только часть времени значения datetime из строки в datetime, однако в вашем примере точность составляет 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, начиная с 1900-01-01. 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
5 голосов
/ 09 февраля 2009

Попробуйте это

AVG(CAST(CAST('1900-01-01 ' + TimeField AS DateTime) AS Float))

Вы действительно должны хранить их в столбце даты и времени в любом случае. Просто используйте последовательную дату для этой части (01.01.1900 очень распространено). Тогда вы можете просто вызвать AVG () и не беспокоиться об этом.

1 голос
/ 19 сентября 2012

Я использовал ответ 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
0 голосов
/ 10 февраля 2009

Я бы вычислил разницу между всеми датами и произвольной точкой (01.01.1900), усреднил ее и затем добавил обратно к произвольной точке.

0 голосов
/ 10 февраля 2009

SQL Server хранит данные даты и времени как 2 4-байтовых целых числа, следовательно, дата и время занимают 8 байтов. Первый - дни с базовой даты, второй - миллисекунды с полуночи.

Вы можете преобразовать значение datetime в целое число и выполнить математические операции, но преобразование возвращает только часть "days" значения datetime, например, выберите команду convert (int, getdate ()). Труднее вернуть часть времени как целое число.

Является ли использование SQL Server 2008 вариантом для вас? Эта версия имеет новый выделенный тип данных времени .

Спасибо, Энди.

0 голосов
/ 09 февраля 2009

Как вы думаете, в среднем по дате и времени?

Я полагаю, что вам нужно сгруппировать по некоторому периоду (час?) И отобразить счетчик (*)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...