sqldatabasevbams-accesstime-and-attendance

MS Access SQL Query for time In/Out attendance


HI,

I'm doing a project which involves time and attendance management. When I download data from the biometric reader, I got the records in the following format,

Lunch Break & Work Time Problem

Attendance Log Table Name: dbo_CHECKINOUT The user Table name is: dbo_USERINFO

+---------+-----------------------+
| USERID  |       CHECKTIME       |
+---------+-----------------------+
|       5 | 2/16/2020 9:33:08 AM  |
|       2 | 2/16/2020 9:57:48 AM  |
|       3 | 2/16/2020 10:07:31 AM |
|       4 | 2/16/2020 10:36:01 AM |
|       1 | 2/16/2020 11:10:10 AM |
|       3 | 2/16/2020 1:45:15 PM  |
|       5 | 2/16/2020 1:57:46 PM  |
|       2 | 2/16/2020 1:58:19 PM  |
|       3 | 2/16/2020 2:17:46 PM  |
|       2 | 2/16/2020 2:33:39 PM  |
|       5 | 2/16/2020 2:48:26 PM  |
|       1 | 2/16/2020 7:51:57 PM  |
|       3 | 2/16/2020 9:29:20 PM  |
|       5 | 2/16/2020 9:29:25 PM  |
|       2 | 2/16/2020 9:29:29 PM  |
|       4 | 2/16/2020 9:29:46 PM  |
|       5 | 2/17/2020 9:31:47 AM  |
|       3 | 2/17/2020 10:15:13 AM |
|       4 | 2/17/2020 10:28:54 AM |
|       1 | 2/17/2020 11:28:17 AM |
+---------+-----------------------+

I want to show the above records as follows, (the Log_In, LB_Out, LB_In, Log_Out, WorkTime and LunchBreak are based on 'time') Someone from StackOverFlow helped me out to make this query

SELECT t.userid, dbo_USERINFO.NAME, DateValue(t.checktime) AS [date], 
Max(IIf(t.counter=0,t.checktime,Null)) AS Log_In, 
Max(IIf(t.counter=1,t.checktime)) AS LB_Out, 
Max(IIf(t.counter=2,t.checktime,Null)) AS LB_In, 
Max(IIf(t.counter=3,t.checktime)) AS Log_Out, 
Format((Log_In-LB_Out)+(LB_In-Log_Out),"hh:nn:ss") AS WorkTime, 
Format(LB_In-LB_Out,"hh:nn:ss") AS LunchBreak
FROM (
    SELECT t.*, 
      (select count(*) from dbo_CHECKINOUT where userid = t.userid and datevalue(checktime) = datevalue(t.checktime) and checktime < t.checktime) AS [counter] FROM dbo_CHECKINOUT AS t)  AS t INNER JOIN dbo_USERINFO ON t.USERID=dbo_USERINFO.USERID
GROUP BY t.userid, dbo_USERINFO.NAME, DateValue(t.checktime);

Results:

userid      date         Log_In        LB_Out        LB_In       Log_Out    WorkTime    LunchBreak
1           16-Feb-20   11:10:10 AM   7:51:57 PM                
1           17-Feb-20   11:28:17 AM                 
2           16-Feb-20   9:57:48 AM    1:58:19 PM    2:33:39 PM  9:29:29 PM  10:56:21     00:35:20
3           16-Feb-20   10:07:31 AM   1:45:15 PM    2:17:46 PM  9:29:20 PM  10:49:18     00:32:31
3           17-Feb-20   10:15:13 AM                 
4           16-Feb-20   10:36:01 AM   9:29:46 PM                
4           17-Feb-20   10:28:54 AM                 
5           16-Feb-20   9:33:08 AM    1:57:46 PM    2:48:26 PM  9:29:25 PM  11:05:37     00:50:40
5           17-Feb-20   9:31:47 AM  

Now the problem is, as you can see Userid:1 & Userid: 4 doesn't have a LunchBreak. So their 1st log would be Log_In & 2nd Log would be as a Log_Out & total work time would be between 1st(Log_In) & 2nd(Log_Out).

Please help to make this possible for me.


Solution

  • This fancy query will return the lunch breaks:

    SELECT 
        dbo_UserInfo.UserId, 
        DateValue([CheckTime]) AS [Date], 
        TimeValue(Min([CheckTime])) AS LogIn, 
    
        (Select Max(TimeValue(T.CheckTime)) 
        From dbo_UserInfo As T 
        Where T.UserId = dbo_UserInfo.UserId 
        And DateValue(T.CheckTime) = DateValue(dbo_UserInfo.CheckTime) 
        And T.CheckTime >
            (Select Min(S.CheckTime) 
            From dbo_UserInfo As S 
            Where S.UserId = dbo_UserInfo.UserId 
            And DateValue(S.CheckTime) = DateValue(dbo_UserInfo.CheckTime))) As LogOut,
    
        (Select Min(TimeValue(T.CheckTime)) 
        From dbo_UserInfo As T 
        Where T.UserId = dbo_UserInfo.UserId 
        And DateValue(T.CheckTime) = DateValue(dbo_UserInfo.CheckTime)
        And T.CheckTime > 
            (Select Min(S.CheckTime) 
            From dbo_UserInfo As S 
            Where S.UserId = dbo_UserInfo.UserId 
            And DateValue(S.CheckTime) = DateValue(dbo_UserInfo.CheckTime))
        And T.CheckTime <
            (Select Max(S.CheckTime) 
            From dbo_UserInfo As S 
            Where S.UserId = dbo_UserInfo.UserId 
            And DateValue(S.CheckTime) = DateValue(dbo_UserInfo.CheckTime))
        Having Count(*) > 1) As LBIn,
    
        (Select Max(TimeValue(T.CheckTime)) 
        From dbo_UserInfo As T 
        Where T.UserId = dbo_UserInfo.UserId 
        And DateValue(T.CheckTime) = DateValue(dbo_UserInfo.CheckTime) 
        And T.CheckTime > 
            (Select Min(S.CheckTime) 
            From dbo_UserInfo As S 
            Where S.UserId = dbo_UserInfo.UserId 
            And DateValue(S.CheckTime) = DateValue(dbo_UserInfo.CheckTime))
        And T.CheckTime <
            (Select Max(S.CheckTime) 
            From dbo_UserInfo As S 
            Where S.UserId = dbo_UserInfo.UserId 
            And DateValue(S.CheckTime) = DateValue(dbo_UserInfo.CheckTime))
        Having Count(*) > 1) As LBOut
    FROM 
        dbo_UserInfo
    GROUP BY 
        dbo_UserInfo.UserId, 
        DateValue([CheckTime]);
    

    From this you can easily calculate the work hours.

    enter image description here

    Revised output:

    enter image description here