出勤:获取灵活的时间表员工的time_in和time_out

时间:2017-06-27 07:17:41

标签: mysql sql database report

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

注意:员工日程安排灵活,可以夜班或白班工作(如员工#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 |

任何建议都表示赞赏。

2 个答案:

答案 0 :(得分:2)

您可以使用自联接将time_in与time_out结合使用,其中time_out在time_in之后。然后只需按time_in对其进行分组,然后只选择第一次time_out:

ömr1, ämr1, ümr1 and pär1 ömr2, ämr2, ümr2 and pär2 ömr3, ämr3, ümr3 and pär3 

答案 1 :(得分: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值,则此方法可能无效。

<强>输出:

enter image description here

在这里演示:

Rextester