我有一个 MySQL 表 temp_employee 如下:
CREATE TABLE `temp_employee` (
`employee_id` varchar(22) COLLATE utf8mb4_unicode_ci NOT NULL,
`application_date` datetime NOT NULL,
PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
表中数据如下:
员工_id | 申请日期 |
---|---|
员工10062808068 | 2023-03-30 07:09:31 |
员工10036984442 | 2023-03-30 09:48:30 |
员工10041499192 | 2023-03-30 09:58:55 |
员工10012314367 | 2023-03-30 03:33:28 |
还有一个表employee_logs如下:
CREATE TABLE `employee_logs` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`employee_id` varchar(22) COLLATE utf8mb4_unicode_ci NOT NULL,
`type` tinyint(1) NOT NULL,
`status` tinyint(1) NOT NULL,
`updated_time` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
employee_logs表中的数据如下:
id | 员工_id | 类型 | 状态 | 更新时间 |
---|---|---|---|---|
1 | emp.10000000001 | 1 | 2 | 2021-04-30 10:19:31 |
2 | emp.10000000002 | 2 | 2 | 2022-06-30 17:29:31 |
3 | 员工10062808068 | 1 | 2 | 2023-03-30 11:19:20 |
4 | emp.10000000003 | 2 | 3 | 2023-03-30 03:03:30 |
5 | emp.10000000004 | 1 | 2 | 2023-03-30 04:04:40 |
6 | 员工10012314367 | 2 | 1 | 2023-03-30 13:13:31 |
7 | 员工10062808068 | 2 | 3 | 2023-03-20 17:24:10 |
8 | 员工10036984442 | 1 | 2 | 2023-03-30 09:09:09 |
9 | 员工10012314367 | 2 | 1 | 2023-03-20 10:10:10 |
10 | 员工10012314367 | 2 | 2 | 2023-03-21 12:12:12 |
我希望Mysql查询获取temp_employee表中每个employee_id的类型、状态和updated_time,该表从employee_logs表中选择单行,条件状态为!= 3 AND Updated_time <= application_date.
预期结果(行数与 temp_employee 表的计数相同)
员工_id | 类型 | 状态 | 更新时间 |
---|---|---|---|
员工10062808068 | 空 | 空 | 空 |
员工10036984442 | 1 | 2 | 2023-03-30 09:09:09 |
员工10041499192 | 空 | 空 | 空 |
员工10012314367 | 2 | 2 | 2023-03-21 12:12:12 |
employee_logs 表非常庞大,有超过 4000 万行,并且可以有多行具有相同的 employee_id。
这是我到目前为止所尝试过的,但没有返回所需的输出
SELECT t.employee_id, oel.type, oel.status, oel.updated_time
FROM (
SELECT t.employee_id, MAX(el.updated_time) updated_time
FROM temp_employee t LEFT JOIN employee_logs el
ON t.employee_id = el.employee_id AND el.status <> 3 AND el.updated_time <= t.application_date
GROUP BY t.employee_id
) t LEFT JOIN employee_logs oel
ON t.employee_id = oel.employee_id AND t.updated_time = oel.updated_time;
employee_logs 表中的说明应根据条件选择哪些行(状态 <> 3 AND Updated_time <= application_date), as follows:
1 emp.10000000001 1 2 2021-04-30 10:19:31 -- should not as emp_id not exists in temp table
2 emp.10000000002 2 2 2022-06-30 17:29:31 -- should not as emp_id not exists in temp table
3 emp.10062808068 1 2 2023-03-30 11:19:20 -- should not return as updated_time > application_date 2023-03-30 07:09:31
4 emp.10000000003 2 3 2023-03-30 03:03:30 -- should not as emp_id not exists in temp table
5 emp.10000000004 1 2 2023-03-30 04:04:40 -- should not as emp_id not exists in temp table
6 emp.10012314367 2 1 2023-03-30 13:13:31 -- should not return as updated_time > application_date 2023-03-30 03:33:28
7 emp.10062808068 2 3 2023-03-20 17:24:10 -- should not return as status = 3
8 emp.10036984442 1 2 2023-03-30 09:09:09 -- should return as updated_time <= application_date && status != 3
9 emp.10012314367 2 1 2023-03-20 10:10:10 -- should not return as updated_time < application_date 2023-03-30 03:33:28 but not latest
10 emp.10012314367 2 2 2023-03-21 12:12:12 -- should return as updated_time < application_date 2023-03-30 03:33:28
查询中任何有助于实现所需输出的帮助都将受到高度赞赏。 TIA
我认为这是一个临时必需的查询,以检查员工是否同意发布的某些更改(或类似内容)
因此,性能不应该是最关键的。
作为第一步,我将使用此查询来确定每个员工的
most recent
状态值。连接 emp_log
表本身,条件为 L.emp_id = R.emp_id and L.update_date < R.update_date
- 并选择结果,其中正确的集合是 null
(意味着,没有关于该员工的更新状态的进一步记录):
SELECT
L.employee_id,
L.type,
L.status,
L.updated_time
FROM
employee_logs L
LEFT JOIN
employee_logs R
on
L.employee_id = R.employee_id AND
L.updated_time < R.updated_time
WHERE
isnull(R.updated_time)
http://sqlfiddle.com/#!9/7a95da/2
现在,您获得了最新的更新 - 只是错过了没有更新的员工 -> 右键加入他们。
SELECT
ifnull(temp.employee_id, e.employee_id) as employee_id,
temp.type,
temp.status,
temp.updated_time,
e.application_date
FROM
(SELECT
L.employee_id,
L.type,
L.status,
L.updated_time
FROM
employee_logs L
LEFT JOIN
employee_logs R
on
L.employee_id = R.employee_id AND
L.updated_time < R.updated_time
WHERE
isnull(R.updated_time)
) as temp
RIGHT JOIN
employees e
ON
temp.employee_id = e.employee_id
http://sqlfiddle.com/#!9/7a95da/10
在最终结果上,您可以根据需要应用您的where条件。 (
WHERE temp.status <> 3 and temp.update_time <= e.application_date)
- 我遗漏了这一点,因为它对我来说没有意义,在员工申请之前就有更新时间......