I am trying to make a query that returns me the number of minutes that a person has worked. A person can have many entries and exits the same day. I would like to know the total number of minutes between entry and exit.
For example: I would like for 20498090R to return 79 minutes
I try with this query but it doesn't work well:
SELECT Empleado,
DATEDIFF("mi", Hora, NextDate)
FROM ( SELECT Empleado,
Hora,
( SELECT MIN(Hora)
FROM [dbo].[Fichajes] T2
WHERE T2.Empleado = T1.Empleado
AND T2.Hora > T1.Hora
) AS NextDate
FROM [dbo].[Fichajes] T1
) AS T
With this query:
12212332W -->
20498090R --> 4
41435568N --> 6
20498090R --> 7055
41435568N -->
20498090R --> 75
20498090R -->
Create a CTE from the sign-in table that is ordered by the employee and the timestamp, and assigns a row number. Now you can join that CTE to itself to find only the rows where an employee both signed in and signed out. Then you can find the minutes worked, and add them up.
;with cte
as (select f.Empleado, f.Hora, f.Entrada, ROW_NUMBER() over (order by f.Empleado, f.Hora) RowNum
from Fichajes f)
select c1.Empleado, SUM(DATEDIFF(mi, c1.Hora, c2.Hora)) MinutesWorked
from cte c1
join cte c2 on c2.Empleado = c1.Empleado and c2.RowNum = c1.RowNum + 1 and c1.Entrada = 1 and c2.Entrada = 0
group by c1.Empleado
Use Cursers something like this:
DECLARE @LV_EMP_CUR CURSOR
DECLARE @LV_EMP VARCHAR(32)
DECLARE @LV_MINUTES FLOAT
SET @LV_EMP_CUR=CURSOR FOR SELECT Empleado FROM TABLE_NAME
OPEN @LV_EMP_CUR FETCH NEXT FROM @LV_EMP_CUR INTO @LV_EMP
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @DT DATETIME
SET @DT = (SELECT HORA FROM TABLE_NAME WHERE EMPLEADO=@LV_EMP)
SET @LV_MINUTES= @LV_MINUTES + SELECT CAST(@DT AS TIME)
FETCH NEXT FROM @LV_EMP_CUR INTO @LV_EMP
END
CLOSE @LV_EMP_CUR
DEALLOCATE @LV_EMP_CUR
I have used a sql window function LEAD to find the next record and partitioned by the user and day. Then calculated the working minutes between two times of the same user and of the same date.
Inserted the data into a temp table to Group by and get the total working minutes. You can use SELECT * FROM #tempTime; before the final select query to see the result what goes into the temp table. It gives an idea if the code is working correctly or not.
Final code:
IF OBJECT_ID('dbo.Fichajes') IS NULL
CREATE TABLE dbo.Fichajes(
[Empleado] [varchar](20) NULL,
[Obra] [varchar](20) NULL,
[Hora] [datetime2](7) NULL,
[Entrada] [bit] NULL,
[Motivo] [varchar](20) NULL,
[Activated] [bit] NULL
)
;
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'12212332W', N'PRY12345', CAST(N'2017-04-17 12:03:00.0000000' AS DateTime2), 1, NULL, NULL)
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'20498090R', N'PRY12345', CAST(N'2017-04-20 12:21:00.0000000' AS DateTime2), 1, NULL, NULL)
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'20498090R', N'PRY12345', CAST(N'2017-04-20 12:25:00.0000000' AS DateTime2), 0, NULL, NULL)
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'41435568N', N'PRY12345', CAST(N'2017-04-20 12:23:00.0000000' AS DateTime2), 1, NULL, NULL)
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'41435568N', N'PRY12345', CAST(N'2017-04-20 12:29:00.0000000' AS DateTime2), 0, NULL, NULL)
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'20498090R', N'PRY12345', CAST(N'2017-04-25 10:00:00.0000000' AS DateTime2), 1, NULL, NULL)
INSERT [dbo].[Fichajes] ([Empleado], [Obra], [Hora], [Entrada], [Motivo], [Activated]) VALUES (N'20498090R', N'PRY12345', CAST(N'2017-04-25 11:15:00.0000000' AS DateTime2), 0, NULL, NULL)
IF OBJECT_ID('tempdb..#tempTime') IS NOT NULL DROP TABLE #tempTime;
with c1 AS
(
SELECT
[Empleado]
,[Obra]
,[Entrada]
,[Motivo]
,[Activated]
,CONVERT(date, Hora) AS [Date]
,CONVERT(time, Hora, 114) AS [Time]
,[Hora]
FROM [dbo].[Fichajes]
)
SELECT
[Empleado]
,[Hora]
,LAG( [Hora]) OVER(PARTITION BY [Empleado], [Date] ORDER BY [Empleado], [Hora] ASC) AS PreviousRecord
,LEAD( [Hora]) OVER(PARTITION BY [Empleado], [Date] ORDER BY [Empleado], [Hora] ASC) AS NextRecord
,DATEDIFF(MINUTE, [Hora], LEAD( [Hora]) OVER(PARTITION BY [Empleado], [Date] ORDER BY [Empleado], [Hora] ASC)) AS [Minutes]
INTO #tempTime
FROM c1
;
SELECT
[Empleado]
,SUM([Minutes]) AS WorkingMinutes
FROM #tempTime
GROUP BY [Empleado]
;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.