简体   繁体   English

MySQL选择当前日期或第二天之间的最新记录

[英]Mysql select the latest record between current day or next day

I have a dataset of daily In and Out times of employees as follows: 我有一个员工的每日进出时间的数据集,如下所示:

uuid    datetime            Status  
7   2019-08-07 07:15:56     Checkout
7   2019-08-06 19:06:00     Checkin
7   2019-08-06 19:05:49     Checkout
7   2019-08-06 08:49:57     Checkin
7   2019-08-06 08:49:46     Checkout
7   2019-08-05 19:00:52     Checkin
7   2019-08-04 17:10:13     Checkout
7   2019-08-04 08:50:04     Checkin
7   2019-08-04 08:49:47     Checkout
7   2019-08-03 18:10:23     Checkin
7   2019-08-03 18:10:13     Checkout
7   2019-08-03 08:41:44     Checkin
7   2019-08-03 08:41:31     Checkout
7   2019-08-02 19:04:55     Checkin
7   2019-08-02 19:04:43     Checkout
7   2019-08-02 08:54:06     Checkin
7   2019-08-02 08:53:49     Checkout
7   2019-08-01 18:55:05     Checkin
7   2019-08-01 07:16:47     Checkout
7   2019-07-31 18:28:11     Checkin
7   2019-07-31 07:15:24     Checkout
7   2019-07-30 19:05:45     Checkin
7   2019-07-30 19:05:33     Checkout
7   2019-07-30 08:56:11     Checkin
7   2019-07-30 08:56:00     Checkout

Using this data I wanted to calculate the total number of hours worked during the day. 使用此数据,我想计算一天中的总工作时间。 The default shifts as 07.00 till 16:00 and 16:00 till 01:00 next day. 默认值从第二天的07.00转移到16:00,从16:00转移到01:00。 From 01:00 till 06:00 OT time. OT时间从01:00到06:00。

My challenge was when an employee Checkins at 07:00 and works till next day morning till 03:00 (both the shifts + few OT hours) I used the following SQL to retrieve the Checkout time but it only return results if checking happens on the same day. 我的挑战是,当一名员工在07:00签入并工作到第二天早上直到03:00(轮班+几个OT时间)时,我使用以下SQL来检索Checkout时间,但它仅在检查发生在同一天。 I'm unable to retrieve results if Checkout time was 03:00, 3:30, 4:00, etc... 如果结帐时间为03:00、3:30、4:00等,我将无法检索结果。

Also there cam be more that one chekins & checkouts that can take place but have to consider the earliest checkin and the latest checkout 此外,可能还会发生一种以上的结账和退房,但必须考虑最早的退房和最新的退房

In the following QUERY I'm trying to retrieve the Checkout time, it only return results if checkout time exists for the same day not if it happens after midnight. 在下面的QUERY中,我尝试检索Checkout时间,它仅在同一天存在checkout时才返回结果,而不是在午夜之后发生。

SELECT uuid, DATE_FORMAT(datetime, "%M %d %Y") AS outdate, DATE_FORMAT(datetime, "%H:%i") AS outtimes FROM attendance_logs WHERE status = 'Checkout' AND (DATE_FORMAT(datetime, "%Y-%m-%d %H:%i:%s") BETWEEN DATE_FORMAT(datetime, "%Y-%m-%d 13:00:00") AND DATE_FORMAT(DATE_ADD(datetime, INTERVAL 1 DAY), "%Y-%m-%d 09:30:00")) AND DATE_FORMAT(datetime, "%Y-%m-%d") < "2019-08-08" ORDER BY datetime DESC 

Expected Output (Edited to fix the result on 2019-08-05) 预期输出(已编辑以将结果固定在2019-08-05)


uuid    date      Checkin   Checkout
7         2019-08-06  08:49:57   07:15:56
7         2019-08-05  19:00:52   08:49:46
7         2019-08-04  08:50:04    17:10:13
7         2019-08-03  08:41:44    08:49:47
7         2019-08-02  08:54:06    08:41:31
7         2019-08-01  18:55:05    08:53:49
7         2019-07-31  07:16:47    18:28:11
7         2019-07-30  08:56:11    07:15:24

Final SQL query 最终SQL查询

 select attendance_logs.uuid
      , emp.name
      , dept.name AS department_name
      , DATE_FORMAT(attendance_logs.datetime
      , "%M %d %Y") AS day
      , cintimes.intimes AS cin 
      , couttimes.outtimes AS cout  
   from attendance_logs 
   left 
   join employees AS emp 
     on emp.uuid = attendance_logs.uuid 
    and emp.is_disabled = 0 
    and emp.is_valid = 1 
   left 
   join departments AS dept 
     on dept.id = attendance_logs.department_id 
    and dept.is_disabled = 0 
    and dept.is_valid = 1 
   left 
   join 
      ( SELECT uuid
             , DATE_FORMAT(datetime, "%M %d %Y") AS indate
             , DATE_FORMAT(datetime, "%H:%i") AS intimes 
          FROM  attendance_logs 
         WHERE status = 'Checkin' 
           AND DATE_FORMAT(datetime, "%Y-%m-%d") <= "2019-08-07" 
         GROUP 
            BY DATE_FORMAT(datetime, "%M %d %Y")
             , uuid 
         ORDER 
            BY datetime DESC ) AS cintimes 
     on cintimes.uuid = attendance_logs.uuid 
    and cintimes.indate = DATE_FORMAT(attendance_logs.datetime, "%M %d %Y") 
   left 
   join 
      ( SELECT uuid
             , DATE_FORMAT(datetime, "%M %d %Y") AS outdate
             , DATE_FORMAT(datetime, "%H:%i") AS outtimes 
          FROM attendance_logs 
         WHERE status = 'Checkout' 
           AND (DATE_FORMAT(datetime, "%Y-%m-%d %H:%i:%s") BETWEEN  DATE_FORMAT(datetime, "%Y-%m-%d 13:00:00") AND  DATE_FORMAT(DATE_ADD(datetime, INTERVAL 1 DAY), "%Y-%m-%d 09:30:00")) 
           AND DATE_FORMAT(datetime, "%Y-%m-%d") < "2019-08-07" 
         ORDER 
            BY datetime DESC ) AS couttimes 
     on couttimes.uuid = attendance_logs.uuid 
    and couttimes.outdate = DATE_FORMAT(attendance_logs.datetime, "%M %d %Y") 
  where attendance_logs.uuid = ? 
  group 
     by DATE_FORMAT(attendance_logs.datetime, "%M %d %Y")
      , attendance_logs.uuid 
  order 
     by attendance_logs.datetime desc

You might want to format it a little bit, but I think that's what you want: 您可能需要格式化一下,但是我想这就是您想要的:

select
   al.uuid,
   al.datetime as checkin,
   (
      select min(datetime) 
      from attendance_logs 
      where status = 'CheckOut' and datetime > al.datetime 
   ) as checkout 
from attendance_logs al 
where al.status = 'CheckIn';

Data set: 数据集:

SELECT * FROM my_table;
+------+---------------------+----------+
| uuid | datetime            | Status   |
+------+---------------------+----------+
|    7 | 2019-07-30 08:56:00 | Checkout |
|    7 | 2019-07-30 08:56:11 | Checkin  |
|    7 | 2019-07-30 19:05:33 | Checkout |
|    7 | 2019-07-30 19:05:45 | Checkin  |
|    7 | 2019-07-31 07:15:24 | Checkout |
|    7 | 2019-07-31 18:28:11 | Checkin  |
|    7 | 2019-08-01 07:16:47 | Checkout |
|    7 | 2019-08-01 18:55:05 | Checkin  |
|    7 | 2019-08-02 08:53:49 | Checkout |
|    7 | 2019-08-02 08:54:06 | Checkin  |
|    7 | 2019-08-02 19:04:43 | Checkout |
|    7 | 2019-08-02 19:04:55 | Checkin  |
|    7 | 2019-08-03 08:41:31 | Checkout |
|    7 | 2019-08-03 08:41:44 | Checkin  |
|    7 | 2019-08-03 18:10:13 | Checkout |
|    7 | 2019-08-03 18:10:23 | Checkin  |
|    7 | 2019-08-04 08:49:47 | Checkout |
|    7 | 2019-08-04 08:50:04 | Checkin  |
|    7 | 2019-08-04 17:10:13 | Checkout |
|    7 | 2019-08-05 19:00:52 | Checkin  |
|    7 | 2019-08-06 08:49:46 | Checkout |
|    7 | 2019-08-06 08:49:57 | Checkin  |
|    7 | 2019-08-06 19:05:49 | Checkout |
|    7 | 2019-08-06 19:06:00 | Checkin  |
|    7 | 2019-08-07 07:15:56 | Checkout |
+------+---------------------+----------+

Here's a partial result... 这是部分结果...

 SELECT x.uuid
      , x.datetime checkin
      , MIN(y.datetime) checkout
   FROM my_table x 
   LEFT 
   JOIN my_table y 
     ON y.datetime > x.datetime 
    AND y.status = 'checkout' 
  WHERE x.status = 'checkin' 
  GROUP 
     BY x.datetime;

+------+---------------------+---------------------+
| uuid | checkin             | checkout            |
+------+---------------------+---------------------+
|    7 | 2019-07-30 08:56:11 | 2019-07-30 19:05:33 |
|    7 | 2019-07-30 19:05:45 | 2019-07-31 07:15:24 |

|    7 | 2019-07-31 18:28:11 | 2019-08-01 07:16:47 |

|    7 | 2019-08-01 18:55:05 | 2019-08-02 08:53:49 |

|    7 | 2019-08-02 08:54:06 | 2019-08-02 19:04:43 |
|    7 | 2019-08-02 19:04:55 | 2019-08-03 08:41:31 |

|    7 | 2019-08-03 08:41:44 | 2019-08-03 18:10:13 |
|    7 | 2019-08-03 18:10:23 | 2019-08-04 08:49:47 |

|    7 | 2019-08-04 08:50:04 | 2019-08-04 17:10:13 |

|    7 | 2019-08-05 19:00:52 | 2019-08-06 08:49:46 |

|    7 | 2019-08-06 08:49:57 | 2019-08-06 19:05:49 |
|    7 | 2019-08-06 19:06:00 | 2019-08-07 07:15:56 |
+------+---------------------+---------------------+

I still can't follow the logic that gets us from here to your desired result. 我仍然无法遵循使我们从这里到达您想要的结果的逻辑。

EDIT: 编辑:

Here's something that looks very like your desired result, but I don't know if it's really what you're after... 这看起来很像您想要的结果,但是我不知道这是否真的是您想要的...

SELECT uuid
     , MIN(checkin) checkin
     , MAX(checkout) checkout
  FROM
     (  SELECT x.uuid
             , x.datetime checkin
             , MIN(y.datetime) checkout
             , DATE(x.datetime-INTERVAL 8 HOUR) dt
          FROM my_table x
          LEFT
          JOIN my_table y
            ON y.uuid = x.uuid
           AND y.datetime > x.datetime
           AND y.status = 'checkout'
         WHERE x.status = 'checkin'
         GROUP
            BY x.datetime
     ) a
 GROUP
    BY uuid
     , dt;
+------+---------------------+---------------------+
| uuid | checkin             | checkout            |
+------+---------------------+---------------------+
|    7 | 2019-07-30 08:56:11 | 2019-07-31 07:15:24 |
|    7 | 2019-07-31 18:28:11 | 2019-08-01 07:16:47 |
|    7 | 2019-08-01 18:55:05 | 2019-08-02 08:53:49 |
|    7 | 2019-08-02 08:54:06 | 2019-08-03 08:41:31 |
|    7 | 2019-08-03 08:41:44 | 2019-08-04 08:49:47 |
|    7 | 2019-08-04 08:50:04 | 2019-08-04 17:10:13 |
|    7 | 2019-08-05 19:00:52 | 2019-08-06 08:49:46 |
|    7 | 2019-08-06 08:49:57 | 2019-08-07 07:15:56 |
+------+---------------------+---------------------+

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM