计算每月准时出勤率

Calculate timely attendance per month

我想计算每个特定日期的员工准时或早到的数量。但在示例中,我将特定的 USERID 作为附加条件。

这是我的 CHECKINOUT table(共 39 行):

USERID      CHECKTIME       CHECKTYPE   VERIFYCODE  SENSORID    WorkCode        sn          UserExtFmt      Update          
1040    02/03/2020 6:54:50      I           1           3           0       0840060140610       0       02/03/2020 10:13:56 
1040    02/03/2020 8:00:00      I           1           2           0       0840060140160       0       02/03/2020 10:50:20 
1040    02/03/2020 16:34:37     I           1           5           0       2809731360643       0       26/03/2020 9:51:41  
1040    03/03/2020 8:02:41      I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    03/03/2020 16:45:00     I           1           5           0       2809731360643       0       26/03/2020 9:51:42  
1040    03/03/2020 16:45:03     I           1           5           0       2809731360643       0       26/03/2020 9:51:42  
1040    04/03/2020 7:57:46      I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    04/03/2020 7:57:48      I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    04/03/2020 17:01:53     I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    04/03/2020 17:01:56     I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    05/03/2020 8:03:45      I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    05/03/2020 8:03:48      I           1           2           0       0840060140160       0       26/03/2020 9:50:49  
1040    05/03/2020 16:41:02     I           1           5           0       2809731360643       0       26/03/2020 9:51:42  
1040    05/03/2020 16:41:05     I           1           5           0       2809731360643       0       26/03/2020 9:51:42  
1040    06/03/2020 8:27:13      I           1           2           0       0840060140160       0       26/03/2020 9:50:50  
1040    06/03/2020 17:26:03     I           1           5           0       2809731360643       0       26/03/2020 9:51:42  
1040    06/03/2020 17:26:06     I           1           5           0       2809731360643       0       26/03/2020 9:51:42  
1040    07/03/2020 11:53:57     I           1           2           0       0840060140160       0       26/03/2020 9:50:50  
1040    09/03/2020 8:01:51      I           1           2           0       0840060140160       0       27/03/2020 10:29:16 
1040    16/03/2020 7:58:20      I           1           2           0       0840060140160       0       26/03/2020 9:50:52  
1040    16/03/2020 7:58:22      I           1           2           0       0840060140160       0       26/03/2020 9:50:52  
1040    16/03/2020 16:34:07     I           1           5           0       2809731360643       0       26/03/2020 9:51:43  
1040    17/03/2020 7:59:05      I           1           2           0       0840060140160       0       26/03/2020 9:50:52  
1040    17/03/2020 16:43:50     0           1           5           0       2809731360643       0       26/03/2020 9:51:44  
1040    18/03/2020 8:00:43      I           1           5           0       2809731360643       0       26/03/2020 9:51:44  
1040    18/03/2020 8:00:46      I           1           5           0       2809731360643       0       26/03/2020 9:51:44  
1040    18/03/2020 16:30:23     I           1           2           0       0840060140160       0       26/03/2020 9:50:52  
1040    19/03/2020 8:03:24      I           1           2           0       0840060140160       0       26/03/2020 9:50:53  
1040    19/03/2020 17:13:44     I           1           2           0       0840060140160       0       26/03/2020 9:50:54  
1040    20/03/2020 8:10:41      I           1           3           0       0840060140610       0       26/03/2020 9:51:10  
1040    20/03/2020 8:10:44      I           1           3           0       0840060140610       0       26/03/2020 9:51:10  
1040    20/03/2020 17:01:41     I           1           5           0       2809731360643       0       26/03/2020 9:51:44  
1040    23/03/2020 8:00:07      I           1           2           0       0840060140160       0       26/03/2020 9:50:54  
1040    23/03/2020 16:38:09     I           1           5           0       2809731360643       0       26/03/2020 9:51:45  
1040    24/03/2020 7:59:08      I           1           5           0       2809731360643       0       26/03/2020 9:51:45  
1040    24/03/2020 7:59:11      I           1           5           0       2809731360643       0       26/03/2020 9:51:45  
1040    24/03/2020 16:39:30     I           1           2           0       0840060140160       0       26/03/2020 9:50:55  
1040    24/03/2020 16:39:33     I           1           2           0       0840060140160       0       26/03/2020 9:50:55  
1040    26/03/2020 8:10:31      I           1           3           0       0840060140610       0       26/03/2020 9:51:11      

这是我的 CHECKEXACT 看起来像:

EXACTID     USERID      CHECKTIME   
404         1040    09/03/2020 8:01:51

我尝试使用 SUM 聚合函数和 IIf 条件来实现此目的,但不幸的是查询给了我错误的结果。

这是我的查询:

SELECT af.USERID, SUM(
        IIf(af.CHECKTIME Is Not Null,
            IIf(WeekDay(DateValue(af.CHECKTIME)) <> 6 And Format(af.CHECKTIME, 'hh:nn:ss') <= '08:15:00', 
                1, IIf(Format(af.CHECKTIME, 'hh:nn:ss') <= '08:30:00', 1, 0)
            ),
            IIf(bf.CHECKTIME Is Not Null,
                IIf(WeekDay(DateValue(bf.CHECKTIME)) <> 6 And Format(bf.CHECKTIME, 'hh:nn:ss') <= '08:15:00', 
                    1, IIf(Format(bf.CHECKTIME, 'hh:nn:ss') <= '08:30:00', 1, 0)
                ), 0
            )
        )
    ) AS [Came On Time or Early]  
FROM (CHECKINOUT AS af
    LEFT JOIN CHECKEXACT bf ON  af.USERID = bf.USERID)
    WHERE af.USERID = 1040 And af.CHECKTIME Between #3/1/2020# And #3/31/2020#  GROUP BY af.USERID

以上查询 returns 这个结果:

USERID  Came On Time or Early
1040            441

我们知道如果我们 COUNT CHECKINOUT table 它将 return 39 行而 CHECKEXACT 只有 return 1 行。但是查询 returns 441 为 [Came On Time or Early]。

我不知道我的查询有什么问题,我想我提出了正确的查询以获取 2020 年 3 月 USERID = 1040 的员工准时或提前到达的总数。

你能告诉我我的查询有什么问题吗?

感谢@June7 通过评论回答这个问题

经过多次检查后,我意识到我写错了查询,尤其是在这一行:

IIf(WeekDay(DateValue(af.CHECKTIME)) <> 6 And Format(af.CHECKTIME, 'hh:nn:ss') <= '08:30:00', 
                1, IIf(Format(af.CHECKTIME, 'hh:nn:ss') <= '08:30:00', 1, 0)
            )

我应该将 ...WeekDay(DateValue(af.CHECKTIME)) <> 6... 分开到另一部分。 如果 af.CHECKTIME 时间大于 '08:30:00' 而当天是星期五,我之前的查询会将星期五视为非星期五。然后会跳到 IIf 我想在另一个工作日运行的错误部分。

而且我应该更改这一行:

...
FROM (CHECKINOUT AS af
    LEFT JOIN CHECKEXACT bf ON  af.USERID = bf.USERID)
...

对此:

...
FROM(
    SELECT af.USERID, MIN(af.CHECKTIME) AS [Tanggal dan Waktu]
        FROM CHECKINOUT AS af
    WHERE af.USERID = 1040 And af.CHECKTIME Between #3/1/2020# And #3/31/2020#
    GROUP BY af.USERID, DateValue(af.CHECKTIME) 
        UNION
    SELECT bf.USERID, MIN(bf.CHECKTIME) AS [Tanggal dan Waktu]
        FROM CHECKEXACT AS bf
    WHERE bf.USERID = 1040 And bf.CHECKTIME Between #3/1/2020# And #3/31/2020#
    GROUP BY bf.USERID, DateValue(bf.CHECKTIME) 
)
...

因为在前面的查询中,From 将打印给定范围内的所有日期时间,而 LEFT JOIN CHECKEXACT 将打印仅一行的 CHECKEXACT 数据(09/03/2020 8:01:51 每次检查都是是的,因为小于 '08:30:00' 并且当然会重复打印 1) 与 CHECKINOUT 的行一样多,而我只需要检查是否存在,这只是 CHECKINOUT 和 CHECKEXACT 每天的最小日期时间。

所以正确的完整查询应该是这样的:

SELECT USERID, 
    SUM(IIf(WeekDay(DateValue([Tanggal dan Waktu])) <> 6,
            IIf(TimeValue([Tanggal dan Waktu]) <= TimeValue('08:30:00'), 
                1, 0
            ),                                      
            IIf(TimeValue([Tanggal dan Waktu]) <= TimeValue('08:30:00'), 1, 0)
        )
    )
    AS [Came On Time or Early]
FROM(
    SELECT af.USERID, MIN(af.CHECKTIME) AS [Tanggal dan Waktu]
        FROM CHECKINOUT AS af
    WHERE af.USERID = 1040 And af.CHECKTIME Between #3/1/2020# And #3/31/2020#
    GROUP BY af.USERID, DateValue(af.CHECKTIME) 
        UNION
    SELECT bf.USERID, MIN(bf.CHECKTIME) AS [Tanggal dan Waktu]
        FROM CHECKEXACT AS bf
    WHERE bf.USERID = 1040 And bf.CHECKTIME Between #3/1/2020# And #3/31/2020#
    GROUP BY bf.USERID, DateValue(bf.CHECKTIME) 
)
GROUP BY USERID

以上查询将打印 6 作为正确/所需的 [Came On Time or Early] 记录。