2013-06-24 103 views
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结果:

 
+----+--------------------+-------+--------+---------------------+------------+---------+---------------------------+-------+----------------------------------------------+ 
| id | select_type  | table | type | possible_keys | key  | key_len |   ref   | rows |     Extra      | 
+----+--------------------+-------+--------+---------------------+------------+---------+---------------------------+-------+----------------------------------------------+ 
| 1 | PRIMARY   | d  | ALL | PRIMARY    |   |   |       | 10 | Using where; Using temporary; Using filesort | 
| 1 | PRIMARY   | a  | ref | PRIMARY,emp_status | emp_status |  5 | orangehrm_li.d.id   | 48 | Using where         | 
| 1 | PRIMARY   | b  | ref | emp_number,skill_id | emp_number |  4 | orangehrm_li.a.emp_number |  1 |            | 
| 1 | PRIMARY   | c  | eq_ref | PRIMARY    | PRIMARY |  4 | orangehrm_li.b.skill_id |  1 | Using where         | 
| 3 | DEPENDENT SUBQUERY | e  | ALL |      |   |   |       | 28165 | Using where; Using filesort     | 
| 2 | DEPENDENT SUBQUERY | e  | ALL |      |   |   |       | 28165 | Using where; Using filesort     | 
+----+--------------------+-------+--------+---------------------+------------+---------+---------------------------+-------+----------------------------------------------+ 
+0

的索引查找深一点,请发表'EXPLAIN SELECT(yourquery)'的输出。 – Bjoern

+0

如果您通过rand()移除您的订单,会发生什么?虽然我可以看到它可能是有用的,但如果您的记录选择很大,可能会使数据库陷入困境。 –

+0

乔,结果通常在20-30行左右。在我的测试中,rand()似乎不成问题。当我删除子查询时,总持续时间小于0.02秒。 –

回答

0

你的表出现小到足以做,因为我在这里做。首先,最内层的查询从所有员工开始,并立即执行两个左连接到预约表...通过获取约会的MAX()小于有问题的日期得到“先前预约”,并获得MIN()之后的任命在获得“下一次预约”之后。所以,现在,对于一个人,我有他们的身份证,并可能根据他们的具体时间先后约会。

现在,我将这个结果首先加入预约表(再次加入左侧),但是这次是基于同一个人(Terp_ID)和他们各自的上一个约会和下一个约会日期/时间。这只会是一个问题,如果你有一个单一的人具有完全相同的日期/时间的多个条目,这只会导致多个记录。

所以现在,我已经为每个人提供了可用的上一个和下一个预约的细节。

剩下的就是简单地加入到其他表格中,以获得“Active”的员工状态以及“阿拉伯”标准的技能组合(我有各自的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)