Mysql 有没有办法计算第一次入住和最后一次退房之间的总休息时间?
MySQL版本为8.0.16 我想获得给定日期的总休息时间,表如下: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
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,并显示签入日期。分区窗口将按
time排序,这样check\u in
只返回前面的条目LAG()
- 我们可以使用当前行的签入时间和前一行的签出时间之间的函数,以分钟为单位确定
中断时间间隔
- 一旦我们确定了每行的这些值;我们可以在子查询()中使用它们,并在特定日期对员工的
进行总和聚合。此外,如果某个特定日期的员工的最后一个条目中没有break\u interval
,则获取签出
签出时间将需要一些特殊处理,因为您需要
,并且NULL
不会返回MAX(…)
NULL
- 您还可以通过在时间和使用范围条件中的check\u上避免使用DATE()函数进行查询
选择版本()
并报告该查询的结果。还有,你的工作时间是多少?是早上8点到下午6点吗?没有午休时间等吗?感谢回复我的MySQL版本是8.0.16,将更新以添加左侧加入午餐时间组等。。因为我试图简化它以便于解释。非常感谢,它真的很有帮助。我将尝试了解更多关于窗口功能的信息,今天学到了一些东西,谢谢。