加入最近的日期

时间:2013-06-24 17:31:29

标签: mysql

我在这里已经阅读了大量的回复,但没有什么比我想象的更好。我目前有一个包含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                  |
+----+--------------------+-------+--------+---------------------+------------+---------+---------------------------+-------+----------------------------------------------+

1 个答案:

答案 0 :(得分: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)