2

我在这里阅读了大量的回复,但没有什么能像我想要的那样有效。我目前有一个包含 2 个子查询的工作查询,问题是执行大约需要 10 秒。我想知道是否有任何方法可以使这更快,也许加入。我似乎无法摆脱它所在的盒子。请让我知道你的想法。

这是工作查询:

Select concat(a.emp_firstname, ' ', a.emp_lastname) as names 
  , if(if (a.emp_gender = 1, 'Male', a.emp_gender)=2, 'Female', 
    if (a.emp_gender = 1, 'Male', a.emp_gender)) as emp_gender 
  , c.name 
  , a.emp_work_telephone
  , a.emp_hm_telephone, a.emp_work_email
  , a.custom7, a.employee_id 
  , a.city_code, a.provin_code, d.name as status, 
  (SELECT cast(concat(DATE_FORMAT(e.app_datetime, '%H:%i'), ' ', e.app_facility) as char(100)) 
     FROM li_appointments.li_appointments as e where e.terp_id = a.employee_id
     and e.app_datetime <= str_to_date('06/26/13 at 3:20 PM', '%m/%d/%Y at %h:%i %p') 
     and date(e.app_datetime) = date(str_to_date('06/26/13 at 3:20 PM', '%m/%d/%Y at %h:%i %p')) 
     order by e.app_datetime desc limit 1) as prevapp, 
  (SELECT cast(concat(DATE_FORMAT(e.app_datetime, '%H:%i'), ' ', e.app_facility) as char(100)) 
     FROM li_appointments.li_appointments as e 
     where e.terp_id = a.employee_id 
     and e.app_datetime > str_to_date('06/26/13 at 3:20 PM', '%m/%d/%Y at %h:%i %p') 
     and date(e.app_datetime) = date(str_to_date('06/26/13 at 3:20 PM', '%m/%d/%Y at %h:%i %p')) 
     order by e.app_datetime desc limit 1) as nextapp 
from hs_hr_employee as a 
Join hs_hr_emp_skill as b on a.emp_number = b.emp_number 
Join ohrm_skill as c on b.skill_id = c.id 
Join orangehrm_li.ohrm_employment_status as d on a.emp_status = d.id 
where c.name like '%Arabic%' 
and d.name = 'Active' order by rand(); 

EXPLAIN结果:

+----+--------+--------+--------+------ ---------------+------------+---------+----------- ----------------+--------+---------- ---------------------+
| 编号 | 选择类型 | 表| 类型 | 可能的键 | 关键 | key_len | 参考 | 行 | 额外 |
+----+--------+--------+--------+------ ---------------+------------+---------+----------- ----------------+--------+---------- ---------------------+
| 1 | 初级 | d | 全部 | 初级 | | | | 10 | 使用哪里;使用临时的;使用文件排序 |
| 1 | 初级 | 一个 | 参考 | PRIMARY,emp_status | emp_status | 5 | orangehrm_li.d.id | 48 | 使用位置 |
| 1 | 初级 | 乙 | 参考 | emp_number,skill_id | emp_number | 4 | orangehrm_li.a.emp_number | 1 | |
| 1 | 初级 | c | eq_ref | 初级 | 初级 | 4 | orangehrm_li.b.skill_id | 1 | 使用位置 |
| 3 | 依赖子查询 | 电子| 全部 | | | | | 28165 | 使用哪里;使用文件排序 |
| 2 | 依赖子查询 | 电子| 全部 | | | | | 28165 | 使用哪里;使用文件排序 |
+----+--------+--------+--------+------ ---------------+------------+---------+----------- ----------------+--------+---------- ---------------------+
4

1 回答 1

0

你的桌子看起来足够小,可以像我在这里做的那样做。首先,最里面的查询从所有员工开始,并立即对约会表进行了两次左连接......通过获得少于相关日期的约会的 MAX() 得到“上一个约会”,并获得MIN() 约会后有问题的日期获得“下一个约会”。所以现在,对于一个人,我有他们的 ID 以及根据他们的具体时间可能的上一个和下一个约会。

现在,我采用该结果并首先重新加入约会表(再次左加入),但这一次基于同一个人 (Terp_ID) 以及他们各自的上一个和下一个约会日期/时间。如果您有多个条目具有完全相同的日期/时间,这只会是一个问题,并且只会导致多个记录。

所以现在,我让每个人都知道之前和下一次约会的具体情况。

剩下的就是简单地加入其他表以仅获得“活动”的员工状态和“阿拉伯语”标准的技能集(我在他们各自的 JOIN 标准中拥有),否则您可以将这些移至 WHERE 子句。

至于查询的“日期/时间”基础,我使用了一次@variable,因此它可以用于两个约会的左连接。最后,我抓住了你想要的各个领域。这应该可以工作,但没有您的数据,可能需要一些调整。

SELECT 
      EmpPrevNext.Employee_ID,
      EmpPrevNext.PrevApnt,
      EmpPrevNext.NextApnt,
      concat(Emp2.emp_firstname, ' ', Emp2.emp_lastname) as names,
      if ( Emp2.emp_gender = 1, 'Male', 'Female' ) as emp_gender, 
      Emp2.emp_work_telephone, 
      Emp2.emp_hm_telephone, 
      Emp2.emp_work_email, 
      Emp2.custom7, 
      Emp2.city_code, 
      Emp2.provin_code, 
      cast( concat( DATE_FORMAT(PriorApp2.app_datetime, '%H:%i'), ' ', PriorApp2.app_facility) as char(100)) 
            as PriorAppointment,
      cast( concat( DATE_FORMAT(NextApp2.app_datetime, '%H:%i'), ' ', NextApp2.app_facility) as char(100)) 
            as NextAppointment,
      EStat.`name` as EmployeeStatus,
      Skill.`name` as SkillName
   FROM
      ( SELECT
              Emp.Employee_ID,
              MAX( PriorApp.app_DateTime ) as PrevApnt,
              MIN( NextApp.app_DateTime ) as NextApnt
           from 
              ( select @DateBasis := '06/26/13 at 3:20 PM' ) sqlvars,
              hs_hr_employee as Emp
                 LEFT JOIN li_appointments.li_appointments as PriorApp
                    ON Emp.Employee_ID = NextApp.Terp_ID
                    AND PriorApp.app_DateTime <= @DateBasis
                 LEFT JOIN li_appointments.li_appointments as NextApp
                    ON Emp.Employee_ID = NextApp.Terp_ID
                    AND NextApp.app_DateTime > @DateBasis
           group by
              Emp.Employee_ID ) EmpPrevNext

         LEFT JOIN li_appointments.li_appointments as PriorApp2
            ON EmpPrevNext.Employee_ID = PriorApp2.Terp_ID
           AND EmpPrevNext.PrevApnt = PriorApp2.app_DateTime

         LEFT JOIN li_appointments.li_appointments as NextApp2
            ON EmpPrevNext.Employee_ID = NextApp2.Terp_ID
           AND EmpPrevNext.NextApnt = NextApp2.app_DateTime

         JOIN hs_hr_employee as Emp2
            ON EmpPrevNext.Employee_ID = Emp2.Employee_ID
            JOIN orangehrm_li.ohrm_employment_status as EStat
               ON Emp2.Emp_Status = EStat.ID
               AND EStat.`name` = 'Active'

            JOIN hs_hr_emp_skill as EmpSkill
              ON Emp2.emp_number = EmpSkill.emp_number
              JOIN ohrm_skill as Skill
                 on EmpSkill.skill_id = Skill.id 
                AND Skill.`name` like '%Arabic%'
   order by 
      rand(); 

确保您的约会表在 (Terp_ID, app_datetime ) 上有一个索引

于 2013-06-24T23:39:07.973 回答