Click here to Skip to main content
15,885,216 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
Dear all,

I have connected zk attendance machine in SQL and import data. but in checkinout table its showing all in one column called checktime. I want to show check in and check out in difference columns.

table name CHECKINOUT and column name checktime.

USERID      CHECKTIME
----------- -----------------------
1           2022-10-04 10:25:44.000
1           2022-10-04 10:25:46.000
1           2022-10-04 10:30:55.000
1           2022-10-04 11:39:23.000
2           2022-10-07 14:05:22.000
2           2022-10-08 09:19:58.000
2           2022-10-08 15:34:53.000


What I have tried:

select * from CHECKINOUT
SQL



USERID      CHECKTIME               CHECKTYPE VERIFYCODE  SENSORID
Posted
Updated 23-Nov-22 0:42am
Comments
Kornfeld Eliyahu Peter 21-Nov-22 3:39am    
You should consult for the machines configuration settings - it may have the proper setting to separate check-in from check-out...
Mohammad Imran1 21-Nov-22 4:59am    
Ok but how to do in sql and separate column check in and check out..
Richard Deeming 21-Nov-22 6:48am    
Probably by using the data in the CHECKTYPE column to determine whether the timestamp is an "in" or "out" event. But since you haven't shown any of the data from that column, that's just a guess.
Mohammad Imran1 21-Nov-22 7:13am    
I want to grab from CHECKTIME column through SQL, because checktype data is incorrect and i want to use only time to first checkin and last checkout. So if you know about SQL please tell me

1 solution

I set up some sample code like this
SQL
declare @demo table (userid int, checktime datetime);
insert into @demo (userid, checktime) values
 (1,'2022-10-04 10:25:44.000')
,(1,'2022-10-04 10:25:46.000')
,(1,'2022-10-04 10:30:55.000')
,(1,'2022-10-04 11:39:23.000')
,(2,'2022-10-07 14:05:22.000')
,(2,'2022-10-08 09:19:58.000')
,(2,'2022-10-08 15:34:53.000');
By using the LEAD [^] function I can get the next datetime in the list for every row and for each userid ..
SQL
select 
	userid, checktime, 
	LEAD(checktime, 1) 
		OVER (partition by userid order by userid, checktime) as nextcheck
from @demo;
Note the partition by in the over clause.
That gives me these results:
userid	checktime				nextcheck
1		2022-10-04 10:25:44.000	2022-10-04 10:25:46.000
1		2022-10-04 10:25:46.000	2022-10-04 10:30:55.000
1		2022-10-04 10:30:55.000	2022-10-04 11:39:23.000
1		2022-10-04 11:39:23.000	NULL
2		2022-10-07 14:05:22.000	2022-10-08 09:19:58.000
2		2022-10-08 09:19:58.000	2022-10-08 15:34:53.000
2		2022-10-08 15:34:53.000	NULL
As you can see there is duplication - nextcheck on row 1 becomes checktime on row 2. You can use a combination of the ROW_NUMBER[^] function and the % (Modulus)[^] operator to correct that. E.g.
SQL
;with cte as
(
	select 
		userid, checktime, 
		LEAD(checktime, 1) 
			OVER (partition by userid order by userid, checktime) as nextcheck, 
		Row_number() OVER (partition by userid order by userid, checktime) as rn
	from @demo
)
select userid, checktime as checkin, nextcheck as checkout
from cte
where rn % 2 = 1;
which gives these results
userid	checkin					checkout
1		2022-10-04 10:25:44.000	2022-10-04 10:25:46.000
1		2022-10-04 10:30:55.000	2022-10-04 11:39:23.000
2		2022-10-07 14:05:22.000	2022-10-08 09:19:58.000
2		2022-10-08 15:34:53.000	NULL
Points to note:
- This assumes your equipment is working well and that your users are disciplined about checking in and checking out.
- note that user 2 checked in but has not checked out - hence the NULL value
- you mentioned in a comment
Quote:
i want to use only time to first checkin and last checkout.
which could done by a simple group by e.g.
SQL
select userid, MIN(checktime) as checkin, MAX(checktime) as checkout
from @demo
group by userid;
giving
userid	checkin						checkout
1		2022-10-04 10:25:44.000	2022-10-04 11:39:23.000
2		2022-10-07 14:05:22.000	2022-10-08 15:34:53.000
But note that for userid = 2 that is actually not a checkout time but the last checkin time (and they are still there).
So, you probably want to do the full list of checkin/checkout first (as above) and then do the min/max on those results.
There should be enough here for you to work it out

EDIT after OP Comment. The following query will generate a list of all dates between two dates, then highlight where dates are missing in the @demo table above
SQL
declare @startdate date = '2022-10-04';
declare @enddate date = '2022-10-10';
WITH q AS
    (
    SELECT  @startdate AS datum
    UNION ALL
    SELECT  dateadd(DAY, 1,datum)
    FROM    q
    WHERE dateadd(DAY, 1,datum) < @enddate
    )
SELECT  datum, d.userid, d.checktime
FROM    q
left outer join @demo d on CAST(d.checktime as date) = q.datum;
If d.userid is null then there was no data for that date.

It's a good idea to have a permanent table of dates generated like this - the join would be the same. That way you can mark up non-working days quite easily - see this link for further information Creating a date dimension or calendar table in SQL Server[^]
 
Share this answer
 
v2
Comments
Mohammad Imran1 29-Nov-22 2:00am    
Ok got it with below query but problem is im unable to get absent record, dates are missing when employ was not present how to add missing dates in below query please help. dates missing
Umair	77	1	2022-11-16	2022-11-16 09:41:25.000	2022-11-16 18:45:46 9:4
Umair	77	1	2022-11-21	2022-11-21 09:29:29.000	2022-11-21 19:00:33	9:31
Umair	77	1	2022-11-25	2022-11-25 09:31:00.000	NULL	NULL
Umair	77	1	2022-11-26	2022-11-26 10:42:55.000	NULL	NULL


I want below result with all missing dates
Umair	77	1	2022-11-16	2022-11-16 09:41:25.000	2022-11-16 18:45:46 9:4
Umair	77	1	2022-11-16	2022-11-17 NULL   NULL NULL
Umair	77	1	2022-11-16	2022-11-18 NULL   NULL NULL
Umair	77	1	2022-11-16	2022-11-19 NULL   NULL NULL
Umair	77	1	2022-11-16	2022-11-20 NULL   NULL NULL
Umair	77	1	2022-11-21	2022-11-21 09:29:29.000	2022-11-21 19:00:33	9:31
Umair	77	1	2022-11-16	2022-11-22 NULL   NULL NULL
Umair	77	1	2022-11-16	2022-11-23 NULL   NULL NULL	NULL


Check my below query
select u.NAME,u.BADGENUMBER, attendance.SENSORID, attendance.CHECKDate, attendance.CheckIn ,attendance.CheckOut
,cast(DATEDIFF(n, attendance.CheckIn, attendance.checkout) / 60 as varchar) + ':' + cast(DATEDIFF(n, attendance.CheckIn, attendance.checkout) % 60 as varchar) as Minutes
from (
    select temp.USERID, temp.SENSORID, temp.CHECKDate ,temp.CheckIn
    ,case when temp.COut = temp.CheckIn then null when temp.CheckIn is null then null else temp.COut end as CheckOut
        from(
            select c.USERID, c.SENSORID, convert(date, CHECKTIME) CHECKDate
            ,(select min(CHECKTIME) from CHECKINOUT cinout where cinout.USERID = c.USERID and cinout.SENSORID = c.SENSORID and cinout.CheckTime >= dateadd(hour, 6, convert(datetime, convert(date, c.CheckTime)))) CheckIn
            ,(select max(CHECKTIME) from CHECKINOUT cinout where cinout.USERID = c.USERID and cinout.SENSORID = c.SENSORID and cinout.CheckTime <= dateadd(hour, 29, convert(datetime, convert(date, c.CheckTime)))) COut
           
 
            from CHECKINOUT c
            group by c.USERID, c.SENSORID, convert(date, CHECKTIME), datename(DW,checktime)
        )temp
) attendance 
inner join userinfo u on u.USERID = attendance.USERID where u.USERID =77
CHill60 29-Nov-22 5:27am    
I am not even going to try to unravel that query - far too many sub-queries. You should also avoid using so many cast/convert functions - worry about how things look only in your presentation layer.
I'll update my solution with some code to show the missing dates
Mohammad Imran1 30-Nov-22 1:00am    
send me your solution avoid above i need missing dates those employee absent
CHill60 30-Nov-22 1:38am    
I've added how to do that to my solution
Mohammad Imran1 30-Nov-22 8:01am    
I have created mycalendar table

Select * from mycalendar

CALENDAR DATE DAY MONTH
2022-11-29 00:00:00.000 29 11
2022 3
2022-11-30 00:00:00.000 30 11 4 2022 4
2022-12-01 00:00:00.000 1 12 4 2022 5
2022-12-02 00:00:00.000 2 12 4 2022 6
2022-12-03 00:00:00.000 3 12 4 2022 7
2022-12-04 00:00:00.000 4 12 4 2022 1

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900