У меня есть два столбца с сотрудником во время и время выхода, но они находятся в 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 protected]' 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 |
+-----------------------------+-----------------------------+
..ит возвращает следующий результат. Это должно было дать мне 09:42 и 11:23. И я даже рассчитал среднее вручную, и он дал разные результаты.
+-------------+--------------+
| AVG_IN_TIME | AVG_OUT_TIME |
+-------------+--------------+
| 01:12 | 01:25 |
+-------------+--------------+
Я пробовал много онлайн-решений, но я не могу использовать ни одно из них, потому что в большинстве из них используется оператор -, что привело к следующему:
Operand data type datetime2 is invalid for subtract operator.
И некоторые ответы пытались преобразовать поле datetime в float, что привело к
Explicit conversion from data type datetime2 to float is not allowed.
Есть ли другой способ сделать это?
Какой у вас выпуск SQL Server?
К вашему сведению, DATEDIFF не возвращает bigint, он возвращает int, и преобразование его в bigint здесь ничего не даст. Если вам нужен bigint, используйте DATEDIFF_BIG и отбросьте CAST.
@VishalGupta Я не могу удалить 0, потому что данные вставлены в этом формате третьей стороной и не могу изменить DateTime2 на DateTime
@dnoeth SQL Server 14.03035
@Larnu Отметил, я сделаю это.


Эти полуночные ряды вызывают эту проблему, они снижают среднее значение.
Вы должны удалить их из среднего вычисления, используя 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 и тоже переключился на секунды, так как вам нужны только минуты в вашем результате.
Спасибо @dnoeth Это чудесно. Я никогда не думал, что эти полуночные столбцы вообще имеют какую-то ценность. Спасибо. :)
Вот способ добиться этого
SELECT (SUM(DATEPART(HOUR, InTime) * 60) + SUM(DATEPART(MINUTE, InTime))) / (SELECT COUNT(InTime) FROM #Temp WHERE DATEPART(HOUR, InTime) <> 0) / 60 AS [InTime avg hours]
, (SUM(DATEPART(HOUR, InTime) * 60) + SUM(DATEPART(MINUTE, InTime))) / (SELECT COUNT(InTime) FROM #Temp WHERE DATEPART(HOUR, InTime) <> 0) % 60 AS [InTime avg minutes]
, (SUM(DATEPART(HOUR, OutTime) * 60) + SUM(DATEPART(MINUTE, OutTime))) / (SELECT COUNT(OutTime) FROM #Temp WHERE DATEPART(HOUR, OutTime) <> 0) / 60 AS [OutTime avg hours]
, (SUM(DATEPART(HOUR, OutTime) * 60) + SUM(DATEPART(MINUTE, OutTime))) / (SELECT COUNT(OutTime) FROM #Temp WHERE DATEPART(HOUR, OutTime) <> 0) % 60 AS [OutTime avg minutes]
FROM #Temp
попробуйте удалить нули из результата