Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 有没有办法计算第一次入住和最后一次退房之间的总休息时间?_Mysql_Sql_Mysql 8.0 - Fatal编程技术网

Mysql 有没有办法计算第一次入住和最后一次退房之间的总休息时间?

Mysql 有没有办法计算第一次入住和最后一次退房之间的总休息时间?,mysql,sql,mysql-8.0,Mysql,Sql,Mysql 8.0,MySQL版本为8.0.16 我想获得给定日期的总休息时间,表如下: id | employee_id | check_in | check_out -------------------------------------------------------------- 1 | 2103 | 2019-09-15 07:30:00 | 2019-09-15 09:20:00 2 | 2103 | 201

MySQL版本为8.0.16

我想获得给定日期的总休息时间,表如下:

id | employee_id  | check_in             | check_out           
--------------------------------------------------------------
 1 | 2103         | 2019-09-15 07:30:00  | 2019-09-15 09:20:00  
 2 | 2103         | 2019-09-15 10:35:00  | null
 3 | 2103         | 2019-09-16 08:00:00  | 2019-09-16 10:00:00
 4 | 2103         | 2019-09-16 11:00:00  | 2019-09-16 18:00:00
 5 | 2095         | 2019-09-16 08:30:00  | 2019-09-16 18:30:00
我的预期结果

id | employee_id  | check_in             | check_out          |  breaks 
--------------------------------------------------------------------------
 1 | 2103         | 2019-09-15 07:30:00  | null               |  75
 3 | 2103         | 2019-09-16 08:00:00  | 2019-09-16 18:00:00|  60
 5 | 2095         | 2019-09-16 08:30:00  | 2019-09-16 18:30:00|  0
我的查询只返回列employee\u id、date、first\u check\u in、last\u check\u out

SELECT 
    a1.employee_id,
    cast(a1.check_in as date) AS date,
    MIN(a1.check_in) AS first_check_in,
    CASE WHEN a2.employee_id IS NULL 
            THEN MAX(a1.check_out)     
        ELSE NULL
    END AS last_check_out
    FROM  attendance_employees AS a1  
    LEFT JOIN attendance_employees AS a2   
        ON a1.employee_id = a2.employee_id
        AND  CAST(a1.check_in AS date) =  CAST(a2.check_in AS date)
        AND a2.check_out IS NULL
    WHERE  1 = 1
    AND DATE(a1.check_in) in ('2019-09-15', '2019-09-16')
    GROUP BY  a1.employee_id, 
    CAST(a1.check_in AS date)
    ORDER BY  a1.employee_id,    
    date
在MySQL中有没有办法计算这个中断时间?谢谢

更新了我的完整查询,包括预期工作时间和休息时间范围的时间段

SELECT  CONCAT(IFNULL(employees.first_name,''),' ',IFNULL(employees.surname,'')) as full_name,
        teams.description,
        time_periods.start_time as start,
        time_periods.end_time as end,
        time_periods.time_period_type,
        time_groups.name,
        cast(a1.check_in as date) AS date,
        MIN(a1.check_in) AS first_check_in,
        CASE WHEN a2.employee_id IS NULL 
                THEN MAX(a1.check_out)     
            ELSE NULL
        END AS last_check_out
        FROM  attendance_employees AS a1  
        LEFT JOIN attendance_employees AS a2   
            ON a1.employee_id = a2.employee_id
            AND  CAST(a1.check_in AS date) =  CAST(a2.check_in AS date)
            AND a2.check_out IS NULL
        JOIN employees
            ON employees.id = a1.employee_id
        JOIN teams
            ON employees.team_id = teams.id
        JOIN time_groups
            ON teams.time_group_id = time_groups.id
        LEFT JOIN day_time_group_time_period
            ON time_groups.id = day_time_group_time_period.time_group_id
            AND day_time_group_time_period.day_id = 3
        LEFT JOIN time_periods
            ON day_time_group_time_period.time_period_id = time_periods.id
        WHERE  1 = 1
        AND DATE(a1.check_in) in ('2019-09-15', '2019-09-16') 
        GROUP BY  a1.employee_id, 
        CAST(a1.check_in AS date),    
        a2.employee_id,
        time_periods.start_time,
        time_periods.end_time,
        time_periods.time_period_type
        ORDER BY  a1.employee_id,    
        date
给出以下结果:

full_name| start   | end     | type| name     | date      | first_check_in     | last_check_out
-----------------------------------------------------------------------------------------------------
EMP1     | 08:00:00| 16:30:00| 1   | Day Shift| 2019-09-16| 2019-09-16 08:45:00| 2019-09-16 19:30:00
EMP1     | 10:00:00| 10:30:00| 2   | Day Shift| 2019-09-16| 2019-09-16 08:45:00| 2019-09-16 19:30:00
EMP1     | 12:00:00| 12:30:00| 2   | Day Shift| 2019-09-16| 2019-09-16 08:45:00| 2019-09-16 19:30:00
EMP2     | 08:00:00| 16:30:00| 1   | Day Shift| 2019-09-15| 2019-09-15 07:30:00| NULL
EMP2     | 10:00:00| 10:30:00| 2   | Day Shift| 2019-09-15| 2019-09-15 07:30:00| NULL
EMP2     | 12:00:00| 12:30:00| 2   | Day Shift| 2019-09-15| 2019-09-15 07:30:00| NULL
在哪里 类型1适用于预期工作时间范围和
类型2适用于预期的中断时间范围。在您的原始问题中,以下方法可行:

SELECT   dt.employee_id,
         Min(dt.check_in) AS check_in,
         CASE WHEN COUNT(dt.check_out) = COUNT(*) THEN MAX(dt.check_out)
              ELSE NULL
         END AS check_out,
         Sum(dt.break_interval) AS break_interval
FROM     (
                  SELECT   employee_id,
                           check_in,
                           check_out,
                           timestampdiff(minute, Lag(check_out) over w, check_in) AS break_interval
                  FROM     attendance_employees
                  WHERE    check_in BETWEEN '2019-09-15 00:00:00' AND      '2019-09-16 23:59:59'
                  WINDOW w AS (partition BY employee_id, date(check_in) ORDER BY check_in ASC) ) dt
GROUP BY dt.employee_id,
         date(dt.check_in);

| employee_id | check_in            | check_out           | break_interval |
| ----------- | ------------------- | ------------------- | -------------- |
| 2095        | 2019-09-16 08:30:00 | 2019-09-16 18:30:00 |                |
| 2103        | 2019-09-15 07:30:00 |                     | 75             |
| 2103        | 2019-09-16 08:00:00 | 2019-09-16 18:00:00 | 60             |

详细信息:

  • 在MySQL 8+中,我们可以使用分析/窗口函数,例如,计算员工在同一日期的前一次签出时间。为了实现这一点,我们的分区窗口将覆盖employee,并显示签入日期。分区窗口将按
    check\u in
    time排序,这样
    LAG()
    只返回前面的条目
  • 我们可以使用当前行的签入时间和前一行的签出时间之间的函数,以分钟为单位确定
    中断时间间隔
  • 一旦我们确定了每行的这些值;我们可以在子查询()中使用它们,并在特定日期对员工的
    break\u interval
    进行总和聚合。此外,如果某个特定日期的员工的最后一个条目中没有
    签出
    ,则获取
    签出时间将需要一些特殊处理,因为您需要
    NULL
    ,并且
    MAX(…)
    不会返回
    NULL
  • 您还可以通过在时间和使用范围条件中的check\u上避免使用DATE()函数进行查询

您的MySQL服务器版本是什么?执行
选择版本()
并报告该查询的结果。还有,你的工作时间是多少?是早上8点到下午6点吗?没有午休时间等吗?感谢回复我的MySQL版本是8.0.16,将更新以添加左侧加入午餐时间组等。。因为我试图简化它以便于解释。非常感谢,它真的很有帮助。我将尝试了解更多关于窗口功能的信息,今天学到了一些东西,谢谢。