Mysql 出勤:灵活安排员工的上班时间和下班时间

Mysql 出勤:灵活安排员工的上班时间和下班时间,mysql,sql,database,report,Mysql,Sql,Database,Report,从下面给定的模式中,我想查询数据库中员工每天进出的时间 注意:员工日程安排是灵活的,他们可以在夜班或白班工作,正如您在员工1中看到的那样 图表:出席人数表 这个查询的问题是我无法从夜班事务中获取时间。这是输出: 这是我的 期望输出 感谢您的建议。如果不使用MySQL不支持开箱即用的分析功能,这个问题将很难解决。但是,我们可以使用会话变量模拟行数。这里的一种方法是根据时间提升在表中的并列位置来分组。考虑下面的查询: SET @row_number = 0; SET @emp_id = NULL;

从下面给定的模式中,我想查询数据库中员工每天进出的时间

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

图表:出席人数表

这个查询的问题是我无法从夜班事务中获取时间。这是输出:

这是我的 期望输出


感谢您的建议。

如果不使用MySQL不支持开箱即用的分析功能,这个问题将很难解决。但是,我们可以使用会话变量模拟行数。这里的一种方法是根据时间提升在表中的并列位置来分组。考虑下面的查询:

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_id和rn_grp列进行分组,然后在原始问题中使用pivot查询方法

请注意,例如,如果员工数据可能有一个IN值而没有相应的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
| 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 |
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      |
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