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

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

我正在编写一个查询,以从表中排除某一组员工。假设我有表1,transaction_details,它包含我想要选择的信息。表2,employee_task_associations,将每个员工映射到特定日期分配给他们的任务。它有一个employee_id字段和一个名为map_id的字段,它是不同任务的id。此表是关联表,因此表1和表3可以具有多对多关系。表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"))

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

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

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"

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

mysql join where
2个回答
1
投票

您似乎在初始查询中很接近,但为什么不将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")

0
投票

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

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

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

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