MySQL 在更新现有的 table 之后用一些计算更新另一个 table 的脚本

MySQL Script for update another table with some calculation after updating the existing table

我已经写了一个 MySQL 查询,它从 clockInTest table 中找到丢失的出勤率,然后插入当天结束时间的新行。但是,我还需要计算那几天的总办公时间和休息时间(新插入的),并且我必须用 timeSpan 和更新 WorkDay table休息时间。以下是我使用的示例数据:

在执行我的查询之前:

Id TimeStamp WorkDayId EmployeeId Type
1 2021-10-26 08:00:00 149 1 Start
2 2021-10-25 08:00:00 148 1 Start
3 2021-10-26 10:00:00 149 1 End
4 2021-10-26 12:00:00 149 1 Start

执行以下查询后:

START TRANSACTION;
INSERT INTO ClockInTest (PartnerId, Timestamp, WorkDayId, UserId, EmployeeId, Type )
SELECT a.PartnerId, CONCAT(DATE(a.TimeStamp),' 23:59:00'), a.WorkDayId, a.UserId, a.EmployeeId, 'End'
FROM  ClockInTest a
WHERE a.Type = 'Start' 
AND a.DeletedAt IS NULL
AND a.TIMESTAMP <= NOW() - INTERVAL 1 DAY
AND NOT EXISTS (
  SELECT 1
  FROM  ClockInTest b
  WHERE b.EmployeeId = a.EmployeeId
  AND a.WorkDayId = b.WorkDayId
  AND a.Timestamp < b.Timestamp
  AND b.Type = 'End'
  AND b.DeletedAt IS NULL
) GROUP BY a.WorkDayId, a.EmployeeId;
SELECT * FROM clockintest WHERE WorkDayId IN (
SELECT DISTINCT c.WorkDayId FROM clockintest c WHERE c.Id >= LAST_INSERT_ID());
COMMIT;

clockInTest table查询执行后:

Id TimeStamp WorkDayId EmployeeId Type
1 2021-10-26 08:00:00 149 1 Start
2 2021-10-25 08:00:00 148 1 Start
3 2021-10-26 10:00:00 149 1 End
4 2021-10-26 12:00:00 149 1 Start
5 2021-10-26 23:59:00 149 1 End
6 2021-10-25 23:59:00 148 1 End

所以,上面table缺失的数据补上了。现在,我必须计算每个 WorkDayId 的总工作时间 (timeSpan) 和休息时间,之后,我必须更新 WorkDay table 如下所示:

工作日table

Id TimeSpan EmployeeId BreakTime
148 1
149 1

工作日的预期结果Table:

Id TimeSpan EmployeeId BreakTime
148 57540000 1 0
149 50,328,000 1 7200000

** TimeSpan 和 BreakTime 以毫秒为单位

我想我们可以为每个 Start 类型组合 tables 数据,并找到各自的 End 时间和 Next Start 时间(如果有的话)

   WorkDayId | EmployeeId | Start | End | Next Start
    148 | 1 | 2021-10-25 08:00:00 | 2021-10-25 23:59:00 
    149 | 1 | 2021-10-26 08:00:00 | 2021-10-26 10:00:00 | 2021-10-26 12:00:00
    149 | 1 | 2021-10-26 12:00:00 | 2021-10-26 23:59:00 | 

那么预期的结果就是时间差异的简单总和

SELECT 
  a.WorkDayId, 
  a.EmployeeId, 
  SUM(TIMESTAMPDIFF(SECOND, a.`TimeStamp`, b.`TimeStamp`)) * 1000 AS timespan,
  SUM(CASE WHEN c.`Timestamp` IS NULL THEN 0 ELSE TIMESTAMPDIFF(SECOND, b.`TimeStamp`, c.`TimeStamp`) END) * 1000 AS breakTime
FROM clockInTest a 
JOIN clockInTest b 
  ON a.EmployeeId = b.EmployeeId 
     AND a.WorkDayId = b.WorkDayId 
     AND b.`Timestamp` > a.`Timestamp`
LEFT JOIN clockInTest c 
  ON a.EmployeeId = c.EmployeeId 
     AND a.WorkDayId = c.WorkDayId 
     AND c.`Type` = 'Start' 
     AND c.`Timestamp` > b.`Timestamp` 
WHERE a.`Type` = 'Start'
AND b.`Type` = 'End'
AND NOT EXISTS (
  SELECT 1
  FROM clockInTest d
  WHERE a.EmployeeId = d.EmployeeId
  AND a.WorkDayId = d.WorkDayId
  AND (
        ( d.`Timestamp` > a.`Timestamp` AND d.`Timestamp` < b.`Timestamp` )
     OR ( d.`Timestamp` > b.`Timestamp` AND d.`Timestamp` < c.`Timestamp` )
  ) 
)
GROUP BY a.WorkDayId, a.EmployeeId
ORDER BY a.WorkDayId, a.EmployeeId

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=eb3b1fef815f1201554fdca683a8448f

要将结果更新为 WorkDay table,假设 WorkDayId 和 EmployeeId 记录存在并且 timespan 和 breakTime 为空

UPDATE WorkDay w
JOIN (
  ... // the above select query
) g ON w.id = g.WorkDayId AND w.EmployeeId = g.EmployeeId
SET w.TimeSpan = g.timespan, w.BreakTime = g.breakTime
;

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2262e5156c0a991eddbbb39ebacfd3bf