mysql中带有case和if条件的迟到和早去查询

Raf*_*fee 5 mysql case

我正在工作的员工时间表,下面是表格。Tech Support部门及Network ie员工实行两班[ 8:00 AM to 2:00 PM ][ 1:00 PM to 7:00 PM ]

以及正常换班[ 9:00 AM to 6:00 PM ]

现在,我正在尝试获取迟到和早退人员的报告。我在服务器端代码上几乎没有逻辑,但它运行得非常慢。所以我想从数据库中制作它。

我在做什么

我正在生成一份报告,迟到早退的员工

算法

  1. 查找员工的开始时间.. 以及相应的部门.. 和相应的班次
  2. 如果员工部门是软件部门,则当天轮班一次,否则当天轮班两次
  3. 从打卡时间和下班时间..找到员工的班次。
  4. 如果员工班次在 First 班次下,则使用 intime as08:00:00 AM和 outtime as01:00:00 PM
  5. 如果员工班次在第二班次下,则使用 intime as02:00:00 PM和 outtime as07:00:00 PM
  6. 如果员工轮班属于正常轮班,则使用 intime as08:55:00 AM和 outtime as06:00:00 PM

然后找到,现在找到它的login_time和log

表格

雇员

emp_id  |   emp_name    |   emp_dept
--------------------------------------
1       |   Billy J     |   1
2       |   Sarah k     |   2
3       |   Takashi M   |   3
4       |   Matsuzaka   |   2
Run Code Online (Sandbox Code Playgroud)

部门

dept_id |   dept_name
--------------------------
1       |   Software
2       |   Tech Support
3       |   Network
Run Code Online (Sandbox Code Playgroud)

员工登录

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
Run Code Online (Sandbox Code Playgroud)

SQL查询,我尝试过,但有点不完整..

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;
Run Code Online (Sandbox Code Playgroud)

Gim*_*mmy 4

下面是这个新的 简化CASE Fiddle的代码这是旧的 CASE 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;
Run Code Online (Sandbox Code Playgroud)

以下是我之前的解决方案:
在这个SQLFiddle中,我对您的范围进行了 4 次查询。这是针对一个部门的查询。我没有使用 CASE 条件,但它有效。一份用于每个时班,一份为所有时间表获取数据。对于后来的情况,我必须删除这一行:ORDER BY Time_in_diff DESC;,以便UNION成功。如果有帮助请告诉我!这是一个带有准备好的语句的解决方案