SQL Sever 2005 中的平均时间值

发布于 2024-07-12 23:48:08 字数 417 浏览 10 评论 0原文

我在 SQL Sever 2005 中有一个 varchar 字段,它以“hh:mm”ss.mmmm”格式存储时间值。

我真正想做的是使用这些时间值的内置聚合函数取平均值。然而,这

SELECT AVG(TimeField) FROM TableWithTimeValues

不起作用,因为(当然)SQL 不会平均 varchars 但是,

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

据我所知,SQL 不知道如何仅用时间来转换值。并且没有将日期转换为日期时间字段,我已经尝试了多种方法来让 SQL 将该字段转换为日期时间,但到目前为止,没有

人能提出更好的方法吗?

I've got a varchar field in SQL Sever 2005 that's storing a time value in the format "hh:mm"ss.mmmm".

What I really want to do is take the average using the built in aggregate function of those time values. However, this:

SELECT AVG(TimeField) FROM TableWithTimeValues

doesn't work, since (of course) SQL won't average varchars. However, this

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

also doesn't work. As near as I can tell, SQL doesn't know how to convert a value with only time and no date into a datetime field. I've tried a wide variety of things to get SQL to turn that field into a datetime, but so far, no luck.

Can anyone suggest a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

属性 2024-07-19 23:48:08

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!

这会将有效值转换为从 1900-01-01 开始的 DATETIME。 SQL Server 根据 1 天 = 1(整数)计算日期。 天的部分是值 1 的部分(即中午是 0.5)。 由于转换中未指定日期,因此 SQL Server 指定了 0 天 (1900-01-01) 值,这满足了我们对时间部分进行平均的需要。

要对 DATETIME 执行 AVG 运算,必须首先将 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

SQL Server can convert a time-only portion of a datetime value from string to datetime, however in your example, you have a precision of 4 decimal places. SQL Server 2005 only recognizes 3 places. Therefore, you will need to truncate the right-most character:

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!

This will convert valid values into a DATETIME starting on 1900-01-01. SQL Server calculates dates based on 1 day = 1 (integer). Portions of days are then portions of the value 1 (i.e. noon is 0.5). Because a date was not specified in the conversion, SQL Server assigned the value of 0 days (1900-01-01), which accommodates our need to average the time portion.

To perform an AVG operation on a DATETIME, you must first convert the DATETIME to a decimal value, perform the aggregation, then cast back. For example

SELECT CAST(AVG(CAST(CAST(LEFT(TimeField, 12) as datetime) AS FLOAT)) AS DATETIME) FROM #TableWithTimeValues
--1900-01-01 05:00:00.000

If you need to store this with an extra decimal place, you can convert the DATETIME to a VARCHAR with time portion only and pad the string back to 13 characters:

SELECT CONVERT(VARCHAR, CAST(AVG(CAST(CAST(LEFT(TimeField, 12) as datetime) AS FLOAT)) AS DATETIME), 114) + '0' FROM #TableWithTimeValues
葵雨 2024-07-19 23:48:08

试试这个

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

无论如何你真的应该将它们存储在日期时间列中。 只需为该部分使用一致的日期(1/1/1900 很常见)。 然后你可以只调用 AVG() 而不用担心它。

Try this

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

You really should store those in a datetime column anyway. Just use a consistent date for that part (1/1/1900 is very common). Then you can just call AVG() and not worry about it.

夜雨飘雪 2024-07-19 23:48:08

我使用 Cadaeic 的回复来获得我正在寻找的答案,所以我认为我应该分享代码......

我正在寻找一个查询,该查询可以平均我所有的时间,并为我提供所有批准的总体周转时间。 下面是一个嵌套语句,它为您提供各个 id 的 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

I used Cadaeic's response to get an answer I was looking for, so I thought I should share the code....

I was looking for a query that would average ALL my times together and give me an overall Turn Around Time for all approvals. Below is a nested statement that gives you the AVG TAT for individual id's and and when nested an overall 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
乜一 2024-07-19 23:48:08

您认为如何计算约会时间的平均值?

我猜你需要按某个时间段(小时?)进行分组,并显示计数(*)?

How do you think to average on datetime?

I guess that you need to GROUP BY some period (Hour?), and display Count(*)?

情话已封尘 2024-07-19 23:48:08

SQL Server 将日期时间数据存储为 2 个 4 字节整数,因此日期时间占用 8 个字节。 第一个是自基准日期以来的天数,第二个是自午夜以来的毫秒数。

您可以将日期时间值转换为整数并执行数学运算,但转换仅返回日期时间值的“天”部分,例如选择convert(int,getdate())。 将“时间”部分作为整数返回更加困难。

使用 SQL Server 2008 适合您吗? 该版本具有新的专用时间数据类型

谢谢,安迪。

SQL Server stores datetime data as 2 4-byte integers, hence a datetime take 8 bytes. The first is days since the base date and the second is milliseconds since midnight.

You can convert a datetime value to an integer and perform mathematical operations, but the convert only returns the "days" portion of the datetime value e.g. select convert(int,getdate()). It is more difficult to return the "time" portion as an integer.

Is using SQL Server 2008 an option for you? That version has a new dedicated time data type.

Thanks, Andy.

最好是你 2024-07-19 23:48:08

我会计算出所有日期和任意点 (01/01/1900) 之间的差异,对其进行平均,然后将其添加回任意点。

I'd work out the difference between all of the dates and an arbitrary point (01/01/1900), average it and then add it back on to the arbitrary point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文