计算每月准时出勤率
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]
记录。
我想计算每个特定日期的员工准时或早到的数量。但在示例中,我将特定的 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]
记录。