Merajuddin Ansari Ответов: 2

Вычислить разницу во времени между двумя временами в mysql


привет, ребята, мне нужна ваша помощь.

мне нужно вычислить разницу во времени всякий раз, когда есть два последовательных I (IN) и O (OUT)
в столбце "статус" а потом придется добавлять все временные разности последовательных I (IN) и O (OUT)

Примечание: - где I (IN) - время входа в компанию, а O (OUT) - время выхода из компании.

emp_no	 attandence_date	       sign_time                status
-------------------------------------------------------------------------
248	2016-09-27 00:00:00.000	   1900-01-01 07:40:59.000	   I
248	2016-09-27 00:00:00.000	   1900-01-01 12:07:54.000	   I
248	2016-09-27 00:00:00.000	   1900-01-01 14:48:20.000	   O
248	2016-09-27 00:00:00.000	   1900-01-01 14:48:38.000	   I
248	2016-09-27 00:00:00.000	   1900-01-01 14:50:24.000	   O
248	2016-09-27 00:00:00.000	   1900-01-01 15:04:08.000	   I
248	2016-09-27 00:00:00.000	   1900-01-01 15:33:04.000	   O
--------------------------------------------------------------------------


Что я уже пробовал:

это функция, которую я создал, но я ищу какой-то простой способ сделать это

ALTER function [dbo].[fn_consumed_hours_inComp]
(
	@emp_id varchar(10),@attDate varchar(12) ,@in1_r varchar(5),@Out1_r varchar(5), @flag bit
)
returns varchar(15)
as

begin

declare @hours int, @totalMinutes int, @minutes int, @counter int, @maxid int, @in1 datetime, @out1 datetime,@status_i char(1),@status_o char(1),
	@hrs int, @mins int, @result varchar(15),@hr char(3), @mn char(3)

if @flag='True' --calculate total hrs in company
begin
	declare @day_att table (loop_id int identity(1,1),in1 datetime, status char(1))
	insert into @day_att(in1,status) select  signtime,status  from EmpAtt where empno = @emp_id and atdate = @attDate order by signtime
	
	select @maxid = count(loop_id) from @day_att
	set @counter = 1
	set @totalMinutes=0

	while @counter <= @maxid
	begin
		select @status_i=status from @day_att where loop_id=@counter
		select @status_o=status from @day_att where loop_id=@counter+1

		if @status_i = 'I' and @status_o ='O'
			begin
				select @in1=in1 from @day_att where loop_id=@counter
				select @out1=in1 from @day_att where loop_id=@counter+1

				select @minutes=DATEDIFF(MINUTE,@in1,@out1)
				set @totalMinutes=@totalMinutes+@minutes
				set @counter = @counter + 2
			end
		else
			set @counter = @counter + 1
	end

		select @hrs = @totalMinutes / 60
		select @mins = @totalMinutes % 60
                select @result = cast(@hrs as varchar(10)) + ':' + cast(@mins as varchar(10))
		
	end

	return @result
end

2 Ответов

Рейтинг:
6

Merajuddin Ansari

declare @day_att table (UserID INT,signtime DATETIME,status CHAR(1))
declare @hrs table (_hours float)
insert into @day_att(UserID,signtime,status) select empno,signtime,status from EmpAtt where empno = 248 and atdate = '2016-09-27' order by signtime

insert into @hrs(_hours) select CAST(DATEDIFF(MINUTE,I.signtime,O.signtime)/60.0 AS float) [Hours]
FROM @day_att I OUTER APPLY (SELECT TOP 1 signtime,status FROM @day_att t WHERE t.UserID = I.UserID AND t.signtime > I.signtime ORDER BY t.signtime) O
WHERE I.status = 'I' AND O.status = 'O'

select sum(_hours) as totalHrs from @hrs


Рейтинг:
15

Suvendu Shekhar Giri

Я видел, как люди легко достигали такого результата, используя APPLY или CTE (Common Table Expression).
Также можно сделать это с помощью временной таблицы и курсора и т. д., Но я использую APPLY или CTE, чтобы гораздо легче устранить вероятность ошибок и все эти сложности.

Пожалуйста, проверьте следующие ссылки, если они могут дать краткое представление о том, что я имею в виду.
sql-вычислить разницу во времени для посещаемости-переполнение стека[^]
sql server-как я могу рассчитать время, проведенное на работе, в одном столбце? - Администраторы Баз Данных Stack Exchange[^]
Преобразование последовательных записей времени в время входа и выхода[^]

Надеюсь, это поможет :)
Пожалуйста, дайте мне знать, если я упускаю здесь что-то очевидное.


Merajuddin Ansari

а как насчет использования Курсора?

Suvendu Shekhar Giri

Вы можете использовать его, но это должен быть последний выбор, я думаю. Это потому, что курсор будет намного медленнее по сравнению с другими подходами.

Merajuddin Ansari

я сделал что-то вроде this.is это нормально.?

объявите таблицу @day_att (UserID INT,signtime DATETIME, status CHAR(1))
объявить таблицу @hrs (_hours float)
вставить @day_att(идентификатор пользователя,signtime,статус) выберите empno,signtime,состояние от EmpAtt где empno = 248 и atdate = '2016-09-27 заказов по signtime

вставить @ч(_hours) выберите литой(функция datediff(минута,И. signtime,О. signtime)/60.0 как поплавок) [часов]
От @day_att я наружное применение (выбрать первые 1 signtime,состояние от @day_att T, где T.Имя пользователя И. имя пользователя и Т.signtime &ГТ; I. порядок signtime на T.signtime) о
Где I. status = ' I 'и O. status = 'O'

выберите sum (_hours) в качестве totalHrs из @hrs