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