我正在处理员工时间表,下面是表格。
部门Tech Support
和Network
的员工有两个班次
即[ 8:00 AM to 2:00 PM ]
和[ 1:00 PM to 7:00 PM ]
正常班次[ 9:00 AM to 6:00 PM ]
现在,我正在努力报告迟到和早退的人。 我在服务器端代码上的逻辑很少,但它的运行速度很慢。所以我想从数据库中创建它。
我正在制作一份报告,即迟到和早退的员工
08:00:00 AM
和时间01:00:00 PM
02:00:00 PM
的正常时间和07:00:00 PM
08:55:00 AM
,将时间设为06:00:00 PM
然后找, 现在找到它的login_time并记录
emp_id | emp_name | emp_dept
--------------------------------------
1 | Billy J | 1
2 | Sarah k | 2
3 | Takashi M | 3
4 | Matsuzaka | 2
dept_id | dept_name
--------------------------
1 | Software
2 | Tech Support
3 | Network
emp_id | login_time | logout_time
----------------------------------------------------------
1 | 2013-02-18 19:10:42 | 2013-02-18 21:27:37
2 | 2013-02-18 19:38:59 | 2013-02-18 22:46:14
3 | 2013-02-18 15:13:53 | 2013-01-01 18:26:39
4 | 2013-01-01 08:41:40 | 2013-01-01 016:41:40
SELECT e.emp_id, e.emp_name, d.dept_name,
CASE d.dept_name
WHEN d.dept_name IN ('Software') THEN
@intime := '08:55:00 AM'
ELSE
@intime := '02:00:00 PM'
END AS `StartingTime`,
@entrytime := DATE_FORMAT(el.login_time, '%r%') AS `Entered into Office`
TIMEDIFF(@entryTime,@intime) `difference`,
IF(TIMEDIFF(@entryTime,@intime)<'00:00:00',NULL,TIMEDIFF(@entryTime,@intime)) AS `Delay`
FROM employees e
INNER JOIN department d ON d.dept_id = e.emp_dept
INNER JOIN employee_login el ON el.emp_id = e.emp_id
WHERE DATE_FORMAT(el.login_time, '%Y-%m-%d') BETWEEN '2013-06-01' AND '2013-06-26'
ORDER BY el.login_time DESC;
答案 0 :(得分:3)
以下是新 简化 CASE Fiddle的代码。这是旧的案例 Fiddle 。
- 如果你愿意,可能不需要一些列,你可以删除它们
- 注意!我必须在每个需要根据部门条件设置的列中使用 CASE 。另外,请注意我已经使用了你在提问时提出的时间安排。如果您想要更改它们,请不要忘记在每个CASE语句中执行此操作,否则您将无法获得所需的结果。
SELECT e.emp_id, d.dept_name, e.emp_name,
CASE d.dept_name
WHEN 'Tech Support' THEN '08:00:00'
WHEN 'Network' THEN '13:00:00'
ELSE '09:00:00'
END AS `StartingTime`,
CASE d.dept_name
WHEN 'Tech Support' THEN '14:00:00'
WHEN 'Network' THEN '19:00:00'
ELSE '18:00:00'
END AS `EndingTime`,
TIME_FORMAT(el.login_time, '%T') AS `Entered_into_Office`,
TIME_FORMAT(el.logout_time, '%T') AS `Left_from_Office`,
CASE d.dept_name
WHEN 'Tech Support' THEN
TIME_FORMAT(TIMEDIFF(TIME_FORMAT(el.login_time, '%T'), TIME_FORMAT('08:00:00', '%T')), '%T')
WHEN 'Network' THEN
TIME_FORMAT(TIMEDIFF(TIME_FORMAT(el.login_time, '%T'), TIME_FORMAT('13:00:00', '%T')), '%T')
ELSE
TIME_FORMAT(TIMEDIFF(TIME_FORMAT(el.login_time, '%T'), TIME_FORMAT('09:00:00', '%T')), '%T')
END AS `Time_in_diff`,
CASE d.dept_name
WHEN 'Tech Support' THEN
TIME_FORMAT(TIMEDIFF(TIME_FORMAT('14:00:00', '%T'), TIME_FORMAT(el.logout_time, '%T')), '%T')
WHEN 'Network' THEN
TIME_FORMAT(TIMEDIFF(TIME_FORMAT('19:00:00', '%T'), TIME_FORMAT(el.logout_time, '%T')), '%T')
ELSE
TIME_FORMAT(TIMEDIFF(TIME_FORMAT('18:00:00', '%T'), TIME_FORMAT(el.logout_time, '%T')), '%T')
END AS `Time_out_diff`,
CASE d.dept_name
WHEN 'Tech Support' THEN TIME_FORMAT(SEC_TO_TIME(
TIME_TO_SEC(TIME_FORMAT(TIMEDIFF(TIME_FORMAT(el.login_time, '%T'), TIME_FORMAT('08:00:00', '%T')), '%T'))
+TIME_TO_SEC(TIME_FORMAT(TIMEDIFF(TIME_FORMAT('14:00:00', '%T'), TIME_FORMAT(el.logout_time, '%T')), '%T'))), '%T')
WHEN 'Network' THEN TIME_FORMAT(SEC_TO_TIME(
TIME_TO_SEC(TIME_FORMAT(TIMEDIFF(TIME_FORMAT(el.login_time, '%T'), TIME_FORMAT('13:00:00', '%T')), '%T'))
+TIME_TO_SEC(TIME_FORMAT(TIMEDIFF(TIME_FORMAT('19:00:00', '%T'), TIME_FORMAT(el.logout_time, '%T')), '%T'))), '%T')
ELSE TIME_FORMAT(SEC_TO_TIME(
TIME_TO_SEC(TIME_FORMAT(TIMEDIFF(TIME_FORMAT(el.login_time, '%T'), TIME_FORMAT('09:00:00', '%T')), '%T'))
+TIME_TO_SEC(TIME_FORMAT(TIMEDIFF(TIME_FORMAT('18:00:00', '%T'), TIME_FORMAT(el.logout_time, '%T')), '%T'))), '%T')
END AS `Total_time_diff`
FROM employees e
INNER JOIN department d ON d.dept_id = e.emp_dept
INNER JOIN employee_login el ON el.emp_id = e.emp_id
WHERE DATE_FORMAT(el.login_time, '%Y-%m-%d') BETWEEN '2012-01-01' AND '2013-12-31'
HAVING Total_time_diff > 0;
以下是我以前的解决方案:
在此 SQLFiddle 中,我针对您的范围进行了4次查询。这是一个部门的查询。我没有使用CASE条件,但它有效。每个时移一个,一个获取所有时间表的数据。对于后者,我必须删除此行:ORDER BY Time_in_diff DESC;
,以便 UNION 成功。如果有帮助,请告诉我!
这是一个 solution with prepared statements 。