【问题标题】:Attendance: Get time_in and time_out of flexible schedule Employees考勤:获取灵活安排的time_in和time_out员工
【发布时间】:2017-11-30 03:45:42
【问题描述】:

从下面给定的架构中,我想在我的数据库中查询员工每天进出的时间。

注意:员工的日程安排很灵活,他们可以在夜班或白班工作(正如您在员工 #1 中看到的那样)。

架构:出勤表

| id | employee_id | timedata            | in_out |
|----|-------------|---------------------|--------|
| 1  | 1           | 2017-06-08 13:51:02 | IN     | <- night shift ( inserted: 2017-06-08)
| 2  | 1           | 2017-06-09 01:10:04 | OUT    | <- actual time_out (inserted: 2017-06-09)
| 3  | 1           | 2017-06-09 14:11:40 | IN     | 
| 4  | 1           | 2017-06-09 19:41:26 | OUT    |
| 5  | 2           | 2017-06-08 09:25:17 | IN     |
| 6  | 2           | 2017-06-08 20:44:14 | OUT    |
| 7  | 2           | 2017-06-09 11:35:00 | IN     |
| 8  | 2           | 2017-06-09 20:36:06 | OUT    |

这是我到目前为止所做的查询:

SELECT employee_id, 
       DATE(timedata) as attendance_date,
       MIN(IF(in_out='IN',timedata,NULL)) AS time_in, 
       MAX(IF(in_out='OUT',timedata,NULL)) AS time_out
FROM attendances
GROUP BY employee_id,DATE(timedata)

这个查询的问题是我无法得到夜班交易的time_out。这是输出:

| employee_id | attendance_date | time_in             | time_out            |
|-------------|-----------------|---------------------|---------------------|
| 1           | 2017-06-08      | 2017-06-08 13:51:02 | NULL                |
| 2           | 2017-06-08      | 2017-06-08 11:25:17 | 2017-06-08 20:44:14 |
| 2           | 2017-06-09      | 2017-06-09 11:35:00 | 2017-06-09 20:36:06 |
| 1           | 2017-06-09      | 2017-06-09 14:11:40 | 2017-06-09 19:41:26 |


这是我的 所需的输出

| employee_id | attendance_date | time_in             | time_out            |
|-------------|-----------------|---------------------|---------------------|
| 1           | 2017-06-08      | 2017-06-08 13:51:02 | 2017-06-09 01:10:04 |
| 2           | 2017-06-08      | 2017-06-08 09:25:17 | 2017-06-08 20:44:14 |
| 1           | 2017-06-09      | 2017-06-09 14:11:40 | 2017-06-09 19:41:26 |
| 2           | 2017-06-09      | 2017-06-09 11:35:00 | 2017-06-09 20:36:06 |

欢迎提出任何建议。

【问题讨论】:

    标签: mysql sql database report


    【解决方案1】:

    如果不使用分析函数,这个问题将很难处理,MySQL 不支持开箱即用。但是,我们可以使用会话变量模拟ROW_NUMBER。这里的一种方法是将INOUT 按时间升序在表格中并列分组。考虑以下查询:

    SET @row_number = 0;
    SET @emp_id = NULL;
    
    SELECT
        t.employee_id,
        DATE(MAX(CASE WHEN in_out = 'IN'  THEN timedata END)) AS attendance_date,
        MAX(CASE WHEN in_out = 'IN'  THEN timedata END) AS time_in,
        MAX(CASE WHEN in_out = 'OUT' THEN timedata END) AS time_out
    FROM
    (
        SELECT *,
            @row_number:=CASE WHEN @emp_id = employee_id THEN @row_number + 1 ELSE 0 END AS rn,
            TRUNCATE(@row_number / 2, 0) AS rn_grp,
            @emp_id:=employee_id
        FROM Attendances
        ORDER BY employee_id, timedata
    ) t
    GROUP BY t.employee_id, t.rn_grp;
    

    要查看其工作原理,我生成的行号将使您的原始表格如下所示:

    | id | employee_id | timedata            | in_out | rn_grp |
    |----|-------------|---------------------|--------|--------|
    | 1  | 1           | 2017-06-08 13:51:02 | IN     | 0      |
    | 2  | 1           | 2017-06-09 01:10:04 | OUT    | 0      |
    | 3  | 1           | 2017-06-09 14:11:40 | IN     | 1      |
    | 4  | 1           | 2017-06-09 19:41:26 | OUT    | 1      |
    | 5  | 2           | 2017-06-08 09:25:17 | IN     | 0      |
    | 6  | 2           | 2017-06-08 20:44:14 | OUT    | 0      |
    | 7  | 2           | 2017-06-09 11:35:00 | IN     | 1      |
    | 8  | 2           | 2017-06-09 20:36:06 | OUT    | 1      |
    

    现在应该清楚了,我们可以按employee_idrn_grp 列进行分组,然后在您的原始问题中使用透视查询方法。

    请注意,如果员工数据可能具有 IN 值而没有相应的 OUT 值,则此方法可能不起作用。

    输出:

    演示在这里:

    Rextester

    【讨论】:

      【解决方案2】:

      您可以使用自连接将 time_in 与 time_out 结合起来,其中 time_out 在 time_in 之后。然后只需按 time_in 分组并只选择第一个 time_out:

      select employee_id, attendance_date,  time_in, MIN(time_out) time_out from (
         select A.id id, DATE(A.timedata) attendance_date, A.employee_id employee_id, A.timedata time_in, A.in_out, B.timedata time_out
         from attendances A
         left join attendances B
             on A.employee_id = B.employee_id
                and A.timedata < B.timedata
                and B.in_out = 'OUT'    
         where A.in_out = 'IN'
      ) AB
      group by employee_id, attendance_date, time_in
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多