通过在 MySQL 中使用 JOIN 优化这些嵌套的 IN 语句

Optimizing these nested IN statements by using JOIN in MySQL

我正在编写一个查询以从 table 中排除某组员工。假设我有 Table 1,transaction_details,其中包含我想要 select 的信息。 Table 2,employee_task_associations,将每个员工映射到他们在特定日期被分配到的任务。它有一个用于 employee_id 的字段,还有一个名为 map_id 的字段,它是不同任务的 ID。这个table是一个关联table所以Tables 1和3可以有多对多的关系。 Table 3,employee_tasks,有一个员工可以拥有的所有任务的列表。

我已经写了这个查询,它是可用的,但没有优化:

SELECT someInfo FROM transaction_details TD
WHERE TD.employee_id NOT IN
  (SELECT employee_id from employee_task_associations ETA
    WHERE map_id IN
      (SELECT id FROM employee_tasks ET
       WHERE ET.taskName = "The task I want to exclude"))

虽然这有效,但它会 运行 多个查询。我想通过将嵌套的 NOT IN 和 IN 语句替换为 JOINS 来加快速度。

我知道我可以用以下内容替换底部四行:

SELECT employee_id FROM employee_task_assocations ETA
  LEFT OUTER JOIN employee_tasks ET
    ON ETA.map_id = ET.id
    WHERE ET.taskName = "The task I want to exclude"

这将return 列出所有执行此任务的员工的 ID。我想通过使用 JOIN 而不是子查询从 transaction_details 的 SELECT 语句中排除这些。我曾尝试使用 LEFT OUTER JOIN WHERE ETA.id IS NULL,但这不起作用。在这种情况下,如何使用 JOIN 排除某些员工?

您的初始查询似乎很接近,但为什么不加入 NOT IN 查询并获得不同的员工...类似

SELECT 
      TD.someInfo 
   FROM 
      transaction_details TD
   WHERE 
      TD.employee_id NOT IN
         (SELECT DISTINCT
                employee_id 
             from 
                employee_task_associations ETA
                   JOIN employee_tasks ET
                      ON ETA.map_id = ET.ID
                      AND ET.taskName = "The task I want to exclude")

您似乎认为外连接比子查询性能更高,但事实并非如此。这完全取决于 SQL 规划器、SQL 优化器、现有索引、table 统计数据,并且最终取决于您的数据库引擎提供的数据运算符库。

此外,您应该考虑在解析之后,查询进入转换阶段,数据库引擎可以自由地以更有效的方式重写您的查询。这意味着即使您编写了子查询,您的查询实际上也可能在后台使用外连接执行。之后 [重写] 查询进入查询规划器,然后进入 SQL 优化器。

优化它的唯一方法是获取所有查询选项的执行计划并进行比较。