在mysql中使用case和if条件的迟到和早期查询

时间:2013-06-28 06:55:44

标签: mysql case

我正在处理员工时间表,下面是表格。 部门Tech SupportNetwork的员工有两个班次 即[ 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. 如果员工转移属于第一班,请使用正常时间08:00:00 AM和时间01:00:00 PM
  5. 如果员工班次处于第二班,请使用02:00:00 PM的正常时间和07:00:00 PM
  6. 的时间
  7. 如果员工班次处于正常班次,请使用正常时间08:55:00 AM,将时间设为06:00:00 PM
  8. 然后找, 现在找到它的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
    

    employee_login

    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
    

    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;
    

1 个答案:

答案 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