【问题标题】:How to optimize this SQL query which select from the same table twice如何优化从同一个表中选择两次的 SQL 查询
【发布时间】:2021-12-19 10:13:32
【问题描述】:

我正在使用员工测试数据库,可在此处获得:https://github.com/datacharmer/test_db

我正在尝试获取与经理姓氏相同的员工的姓名。我希望使下面的查询更快。

SELECT concat(first_name,' ',last_name) 
FROM  
((employees JOIN dept_emp ON employees.emp_no=dept_emp.emp_no) 
JOIN dept_manager ON dept_emp.dept_no=dept_manager.dept_no) 
WHERE employees.last_name=
(SELECT last_name FROM employees WHERE employees.emp_no=dept_manager.emp_no);

如您所见,where 子句中有一个select 用于搜索整个表。我假设这意味着对于连接表的每一行,它将是整个 employees 表。 我试图通过在加入之前创建一个较小的表来解决它,但它甚至慢了 4 倍。

SELECT concat(B.first_name,' ',B.last_name)
FROM 
(SELECT employees.emp_no, employees.last_name, dept_no 
FROM employees JOIN dept_manager ON employees.emp_no=dept_manager.emp_no) AS A
JOIN
(SELECT employees.first_name, employees.emp_no, last_name, dept_no 
FROM employees JOIN dept_emp ON  employees.emp_no=dept_emp.emp_no) AS B
ON (A.dept_no=B.dept_no AND A.last_name=B.last_name);

【问题讨论】:

  • 什么版本的 MySQL? 8.0 有WITH
  • 8.0版,你能写一个查询吗?索引显然使事情变得更快,所以我只是在寻找查询改进
  • 一个部门可以有多个经理吗?如果没有,删除表dept_manager 并在表departments 中添加dept_emp_no。如果您想记录谁在何时为某个部门工作并跟踪他们的动向?
  • 嗯,模式已经给出,所以我不能改变它。每个部门可以有超过 1 名经理,但在不同的时间(基本上是历史)
  • 您想要当前员工的姓名...? to_date 是未来的某个时间吗?或者NULL 的意思是“当前”?否则,很难在不知情的情况下优化查询。

标签: mysql sql query-optimization


【解决方案1】:
    SELECT 
    CONCAT_WS(' ', first_name, last_name) AS fullName
FROM employees 
    JOIN dept_emp ON dept_emp.emp_no=employees.emp_no
    JOIN dept_manager ON dept_manager.dept_no=dept_emp.dept_no
    # added after comment from Rick James
        AND dept_manager.from_date <= emp.end_date 
            AND emp.from_date <= dept_manager.to_date
    JOIN employees managers ON managers.emp_no=dept_manager.emp_no 
        AND managers.last_name=employees.lastname

从我的头顶。顺便说一句,没有测试。

并添加一个索引: 姓氏

ALTER TABLE `employees` 
ADD INDEX `idx_lastName`(`last_name`) USING BTREE;

【讨论】:

  • 在最后一行,没有表管理器
  • @HuyLe 我将员工表别名为那里的经理。我刚刚重新加入员工担任经理
  • 在倒数第二行,“AND dept_manager”缺少一些东西。如果我删除它,这个查询会变得和我的慢版本一样慢。如果我添加“dept_manager.emp_no=dept_emp.emp_no”,则结果不正确(只显示经理)
  • 抱歉,已编辑答案。也不要忘记将索引添加到 last_name
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-14
  • 2021-12-08
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
相关资源
最近更新 更多