从DateTime2列计算平均时间

时间:2019-01-09 10:31:53

标签: sql sql-server

我有两列与员工的时间和超时时间,但它们在DateTime2中。

+-----------------------------+-----------------------------+-----------------------------+
|            Date             |           InTime            |           OutTime           |
+-----------------------------+-----------------------------+-----------------------------+
| 2019-01-01 00:00:00.0000000 | 2019-01-01 09:45:00.0000000 | 2019-01-01 11:14:00.0000000 | <
| 2019-01-02 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 2019-01-03 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 2019-01-04 00:00:00.0000000 | 2019-01-04 18:32:00.0000000 | 1901-01-01 00:00:00.0000000 | <
| 2019-01-05 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 2019-01-06 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 2019-01-07 00:00:00.0000000 | 2019-01-07 14:17:00.0000000 | 2019-01-07 15:03:00.0000000 | <
| 2019-01-08 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
+-----------------------------+-----------------------------+-----------------------------+

因此,如您所见,有些行包含时间,有些则不包含时间。我要删除的是日期部分,并获取两列的平均时间。

到目前为止,我一直在使用此查询。

SELECT  CONVERT(varchar(5), 
            Cast(DateAdd(ms, AVG(CAST(DateDiff( ms, '00:00:00', cast(InTime as time)) AS bigint)), '00:00:00' ) as Time ),108) AS 'AVG_IN_TIME',
        CONVERT(varchar(5), 
            Cast(DateAdd(ms, AVG(CAST(DateDiff( ms, '00:00:00', cast(OutTime as time)) AS bigint)), '00:00:00' ) as Time ),108) AS 'AVG_OUT_TIME'
FROM [HCMSync].[dbo].[Attendances]
Where [Email address] = 'email@domain.com' and [Date] between '2019-01-01' and '2019-01-08'

但这给了我

+-------------+--------------+
| AVG_IN_TIME | AVG_OUT_TIME |
+-------------+--------------+
| 05:19       | 03:17        |
+-------------+--------------+

我认为这是不正确的,因为如果这样的话,随着时间的推移只有一条记录,

+-----------------------------+-----------------------------+
|           InTime            |           OutTime           |
+-----------------------------+-----------------------------+
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
| 2019-01-07 09:42:00.0000000 | 2019-01-07 11:23:00.0000000 | < This record.
| 1901-01-01 00:00:00.0000000 | 1901-01-01 00:00:00.0000000 |
+-----------------------------+-----------------------------+

.. it返回以下结果。它应该为我提供了09:42和11:23。我什至手动计算了平均值,并返回了不同的结果。

+-------------+--------------+
| AVG_IN_TIME | AVG_OUT_TIME |
+-------------+--------------+
| 01:12       | 01:25        |
+-------------+--------------+

我尝试了许多在线解决方案,但是我不能使用其中任何一个,因为其中大多数使用-运算符并导致

  

操作数数据类型datetime2对于减法运算符无效。

一些答案​​试图将datetime字段转换为float,结果是,

  

不允许从数据类型datetime2到float的明确转换。

还有其他方法吗?

2 个答案:

答案 0 :(得分:2)

那些午夜行会导致此问题,它们会降低平均值。

您必须使用NULLIF将其从平均计算中删除。

SELECT  CONVERT(varchar(5), 
            Cast(DateAdd(s, AVG(NULLIF(DateDiff( s, '00:00:00', cast(InTime as time)), 0)), '00:00:00' ) as Time ),108) AS 'AVG_IN_TIME',
        CONVERT(varchar(5), 
            Cast(DateAdd(s, AVG(NULLIF(DateDiff( s, '00:00:00', cast(OutTime as time)),0)), '00:00:00' ) as Time ),108) AS 'AVG_OUT_TIME'

我也删除了bigint演员表,并切换到秒,因为您只希望获得几分钟的结果。

答案 1 :(得分:0)

这是实现这一目标的一种方法

for attachment in "${attachments[@]}"; do
    IFS=, read -r name path type <<<"$attachment"
    attachmentFilename+=( "$name" )
    attachmentPath+=( "$path" )
    attachmentType+=( "$type" )
done
相关问题