Вычислить среднее время из столбца DateTime2

У меня есть два столбца с сотрудником во время и время выхода, но они находятся в 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.

Есть ли другой способ сделать это?

попробуйте удалить нули из результата

Vishal Gupta 09.01.2019 11:38

Какой у вас выпуск SQL Server?

dnoeth 09.01.2019 11:43

К вашему сведению, DATEDIFF не возвращает bigint, он возвращает int, и преобразование его в bigint здесь ничего не даст. Если вам нужен bigint, используйте DATEDIFF_BIG и отбросьте CAST.

Larnu 09.01.2019 11:44

@VishalGupta Я не могу удалить 0, потому что данные вставлены в этом формате третьей стороной и не могу изменить DateTime2 на DateTime

Nishan 09.01.2019 11:54

@dnoeth SQL Server 14.03035

Nishan 09.01.2019 11:54

@Larnu Отметил, я сделаю это.

Nishan 09.01.2019 11:54
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
6
384
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 и тоже переключился на секунды, так как вам нужны только минуты в вашем результате.

Спасибо @dnoeth Это чудесно. Я никогда не думал, что эти полуночные столбцы вообще имеют какую-то ценность. Спасибо. :)

Nishan 09.01.2019 12:03

Вот способ добиться этого

    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

Другие вопросы по теме