从考勤表MYSQL中查找最后一名和最后一名

从考勤表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

我有一个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
我希望输出为最后一个时钟输入和最后一个时钟输出,如下所示。如果在最后一次时钟输入后没有时钟输出,只需忽略时钟输入

   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

我真的不知道该怎么做。我问过我的同事,目瞪口呆地寻找答案,但运气不好。非常感谢你们的帮助。提前感谢。

这是间隙问题的一种变体。首先枚举
in
s和
out
s中的
,使连续值组具有相同的值。然后您就可以使用聚合了

因此:


这是一个SQL问题。

这是间隙问题的变体。首先枚举
in
s和
out
s中的
,使连续值组具有相同的值。然后您就可以使用聚合了

因此:


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

SQL:

输出:

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)

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

SQL:

输出:

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)

感谢你的回答!我会尝试你的建议,并会让你知道它是否有效。:)嗨,Gordon,这个查询很有效,但它仍然提供所有的时钟输入和时钟输出,而不是我想要的最后输入和最后输出。但很高兴你给了我一些想法。它在SQL Fiddle中工作得非常完美,但在我本地的mysql中却不行。我编辑查询并将employee\u id=:employee\u id和datetime=:datetime放在其中。它给我所有的集合,每对中的一个都有空值。也许你应该问另一个问题。您的问题中没有
employee\u id
,此答案似乎正确回答了您提出的问题。是。你的回答回答了我的问题。只是我没有在这里工作。我将尝试找出原因,也许需要改进代码以使其正常工作。非常感谢你的回答!:)感谢你的回答!我会尝试你的建议,并会让你知道它是否有效。:)嗨,Gordon,这个查询很有效,但它仍然提供所有的时钟输入和时钟输出,而不是我想要的最后输入和最后输出。但很高兴你给了我一些想法。它在SQL Fiddle中工作得非常完美,但在我本地的mysql中却不行。我编辑查询并将employee\u id=:employee\u id和datetime=:datetime放在其中。它给我所有的集合,每对中的一个都有空值。也许你应该问另一个问题。您的问题中没有
employee\u id
,此答案似乎正确回答了您提出的问题。是。你的回答回答了我的问题。只是我没有在这里工作。我将尝试找出原因,也许需要改进代码以使其正常工作。非常感谢你的回答!:)这个答案很好用!非常感谢你!你救了我的命!这个答案很好用!非常感谢你!你救了我的命!
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)