Mysql 查询使用左连接根据其他列值查找行

问题描述 投票:0回答:1

我有一个 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

mysql join left-join
1个回答
0
投票

我认为这是一个临时必需的查询,以检查员工是否同意发布的某些更改(或类似内容)

因此,性能不应该是最关键的。

作为第一步,我将使用此查询来确定每个员工的

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)
- 我遗漏了这一点,因为它对我来说没有意义,在员工申请之前就有更新时间......

© www.soinside.com 2019 - 2024. All rights reserved.