我目前有一张表格,代表员工的开始和停止工作时间:
员工完成后需要更新check_out。
最好有一张表如下吗?
要确定员工是否已经签入了我必须检查的内容,请检查给定员工的最后一条记录是否具有CHECKIN的event_type。此外,不再需要获取记录并更新记录。
第二种方法更好吗?或者您有其他建议吗?
答案 0 :(得分:3)
如果可能的话,使用event_type_id而不是event_type和另一个表event_type或只是一个常量数组,例如。
array_event_name = array(1 => CHECKIN,2 => CHECKOUT,3 => INTERVAL_IN,4 => INTERVAL_OUT)
答案 1 :(得分:3)
选项1更易于构建,并且查询更简单。找出谁签到但没有签出是一个简单的查询;找到每个员工的总工作时间也很简单。这种简单性可能意味着它对于常见查询会更快。我看到的唯一缺点是它更难扩展。例如,如果要为“午休时间”捕获不同的事件类型,则必须添加额外的列。
选项2更灵活 - 您可以在不更改架构的情况下添加新事件类型。但是,简单的查询 - 员工x在6月工作了多少小时 - 非常棘手。您需要付出额外努力的灵活性。
所以,这取决于你所说的“更好”。
答案 2 :(得分:3)
我知道这篇文章已经过时了,但这适用于那些仍在寻找解决方案的人:
出勤表格结构
id | int
employee_code | varchar
status | enum('check_in','check_out')
created | datetime
数据强>
id employee_code status created
1 EMP0001 check_in 2016-08-20 09:30:30
2 EMP0001 check_out 2016-08-20 18:15:00
3 EMP0002 check_in 2016-08-21 14:52:48
4 EMP0002 check_out 2016-08-21 21:09:18
<强>查询强>
SELECT
A1.employee_code,
A1.created AS check_in_at,
A2.created AS check_out_at,
TIMEDIFF(A2.created, A1.created) AS total_time
FROM
tbl_attendances AS A1
INNER JOIN tbl_attendances AS A2
ON A1.employee_code = A2.employee_code
AND DATE(A1.created) = DATE(A2.created)
WHERE 1 = 1
AND A1.status = 'check_in'
AND A2.status = 'check_out'
AND DATE(A1.created) BETWEEN '2016-08-20'
AND '2016-08-21'
AND DATE(A2.created) BETWEEN '2016-08-20'
AND '2016-08-21'
ORDER BY A1.created DESC
<强>结果
employee_code check_in_at check_out_at total_time
EMP0002 2016-08-21 14:52:48 2016-08-21 21:09:18 06:16:30
EMP0001 2016-08-20 09:30:30 2016-08-20 18:15:00 08:44:30
对于特定员工,在AND A1.employee_code = 'EMP0001'
子句
WHERE
答案 3 :(得分:1)
我会选择第二个。
然而,主要问题和业务规则将是相同的,并且可以通过任何一种方法进行回答。答案 4 :(得分:1)
使用第一个选项,数据库本身可以更好地保护自己免受某些异常 1 。一些异常仍然可能 2 ,但这是一个开始。
另一方面,InnoDB表是群集的,群集表中的二级索引可能很昂贵(请参阅this article中的“群集的缺点”),如果需要考虑的话您需要查询check_out
。
使用第二个选项,即使对于可以通过数据库设计纯粹以声明方式预防的异常,您依赖于命令式代码。
从好的方面来说,你不太可能需要二级索引。
简而言之,除非您需要二级索引,否则请使用第一个选项。如果您确实需要二级索引,则根据您希望实现的index covering类型,您可以使用任一选项。
1 例如在没有首次办理登机手续的情况下退房。
2 例如再次办理登机手续,无需先退房,重叠“stints”等...
答案 5 :(得分:1)
我会选择第一个选项。将两个时间戳放在一行将增加您的搜索时间,并使您的计算更容易。
假设您想计算一天员工的工作时间。您的搜索将在匹配的第一行停止,您将获得所有必需的数据。您不必深入挖掘选项2的情况。选项1还通过每次登记/退房仅使用1行来减少您的工作台大小。
选项2确实有一个优势。签出时,您的数据库必须进行搜索以更新选项1的数据。对于选项2,它只是一个写入。
考虑到您将不止一次搜索数据这一事实,您可以放弃直接插入优势,以获得更好的结构和更快的搜索。虽然最后的选择取决于你。
祝你好运!