mysql - 从考勤表MYSQL中查找最后一个和最后一个

标签 mysql

我有一个MYSQL考勤表,记录如下:

   Id   DateTime             Door Employee_id
    1   2016-01-01 08:00:00  In   100
    2   2016-01-01 09:00:00  Out  100
    3   2016-01-01 09:15:00  In   100
    4   2016-01-01 09:30:00  In   100
    5   2016-01-01 10:00:00  Out  100
    6   2016-01-01 11:00:00  In   100
    7   2016-01-01 12:00:00  In   100
    8   2016-01-01 13:00:00  In   100
    9   2016-01-01 13:30:00  Out  100
   10   2016-01-01 14:00:00  Out  100
   11   2016-01-01 15:00:00  In   100

我希望输出为 Last Clock In 和 Last Clock Out,如下所示。如果上次打卡后没有打卡,则忽略打卡。

   Id   Clock In             Clock Out             Employee Id
    1   2016-01-01 08:00:00  2016-01-01 09:00:00   100
    2   2016-01-01 09:30:00  2016-01-01 10:00:00   100
    3   2016-01-01 13:00:00  2016-01-01 14:00:00   100

我真的不知道如何执行此操作。我已经问过我的同事并努力寻找答案,但没有运气。感谢你们的帮助。提前致谢。

最佳答案

这是一个带有演示的解决方案。

SQL:

-- data
create table attendance(Id int, DateTime datetime, Door char(20));
INSERT INTO attendance VALUES
(    1,   '2016-01-01 08:00:00',  'In'),
(    2,   '2016-01-01 09:00:00',  'Out'),
(    3,   '2016-01-01 09:15:00',  'In'),
(    4,   '2016-01-01 09:30:00',  'In'),
(    5,   '2016-01-01 10:00:00',  'Out'),
(    6,   '2016-01-01 11:00:00',  'In'),
(    7,   '2016-01-01 12:00:00',  'In'),
(    8,   '2016-01-01 13:00:00',  'In'),
(    9,   '2016-01-01 13:30:00',  'Out'),
(   10,   '2016-01-01 14:00:00',  'Out'),
(   11,   '2016-01-01 15:00:00',  'In');
SELECT * FROM attendance;

-- SQL needed:
SELECT 
    @id:=@id+1 Id,
    MAX(IF(Door = 'In', DateTime, NULL)) `Check In`,
    MAX(IF(Door = 'Out', DateTime, NULL)) `Check Out`
FROM
    (SELECT 
        *, 
        CASE 
            WHEN 
                (door = 'In' AND @last_door = '') OR
                (door = 'In' AND @last_door = 'In') OR
                (door = 'Out' AND @last_door = 'In') OR
                (door = 'Out' AND @last_door = 'Out')
            THEN @group_num
            WHEN
                (door = 'In' AND @last_door = 'Out')
            THEN @group_num:=@group_num+1
        ELSE 0
        END door_group,
        @last_door:=Door
    FROM attendance 
        JOIN (SELECT @group_num:=1) a
    ) t JOIN (SELECT @id:=0) b
GROUP BY t.door_group
HAVING SUM(Door = 'In') > 0 AND SUM(Door = 'Out') > 0;

输出:

mysql> SELECT * FROM attendance;
+------+---------------------+------+
| Id   | DateTime            | Door |
+------+---------------------+------+
|    1 | 2016-01-01 08:00:00 | In   |
|    2 | 2016-01-01 09:00:00 | Out  |
|    3 | 2016-01-01 09:15:00 | In   |
|    4 | 2016-01-01 09:30:00 | In   |
|    5 | 2016-01-01 10:00:00 | Out  |
|    6 | 2016-01-01 11:00:00 | In   |
|    7 | 2016-01-01 12:00:00 | In   |
|    8 | 2016-01-01 13:00:00 | In   |
|    9 | 2016-01-01 13:30:00 | Out  |
|   10 | 2016-01-01 14:00:00 | Out  |
|   11 | 2016-01-01 15:00:00 | In   |
+------+---------------------+------+
11 rows in set (0.00 sec)

mysql>
mysql> -- SQL needed:
mysql> SELECT
    ->     @id:=@id+1 Id,
    ->     MAX(IF(Door = 'In', DateTime, NULL)) `Check In`,
    ->     MAX(IF(Door = 'Out', DateTime, NULL)) `Check Out`
    -> FROM
    ->     (SELECT
    ->         *,
    ->         CASE
    ->             WHEN
    ->                 (door = 'In' AND @last_door = '') OR
    ->                 (door = 'In' AND @last_door = 'In') OR
    ->                 (door = 'Out' AND @last_door = 'In') OR
    ->                 (door = 'Out' AND @last_door = 'Out')
    ->             THEN @group_num
    ->             WHEN
    ->                 (door = 'In' AND @last_door = 'Out')
    ->             THEN @group_num:=@group_num+1
    ->         ELSE 0
    ->         END door_group,
    ->         @last_door:=Door
    ->     FROM attendance
    ->         JOIN (SELECT @group_num:=1) a
    ->     ) t JOIN (SELECT @id:=0) b
    -> GROUP BY t.door_group
    -> HAVING SUM(Door = 'In') > 0 AND SUM(Door = 'Out') > 0;
+------+---------------------+---------------------+
| Id   | Check In            | Check Out           |
+------+---------------------+---------------------+
|    1 | 2016-01-01 08:00:00 | 2016-01-01 09:00:00 |
|    2 | 2016-01-01 09:30:00 | 2016-01-01 10:00:00 |
|    3 | 2016-01-01 13:00:00 | 2016-01-01 14:00:00 |
+------+---------------------+---------------------+
3 rows in set (0.00 sec)

关于mysql - 从考勤表MYSQL中查找最后一个和最后一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35931382/

相关文章:

php - 在 Laravel/Lumen Eloquent 中获取两个日期之间的所有年份

MySql:选择以 "\"字符开头的记录

php - Laravel 中使用 Modal 动态更新数据

Mysql触发器不适用于更新查询

mysql - 在 Perfect 框架中使用 MySQL 连接器

php - 通过 phpMyAdmin 执行 MySql #1243 错误

sql - MySQL,删除带有连接的查询

php - while 循环内查询

mysql - 多次加入来收集用户评分?

mysql - 用两个条件连接mysql中的三个表