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
我已经写了一个 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