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 | テーブル | タイプ | 可能な_キー | キー | key_len | 参照 | 行 | 行 エクストラ |
+----+--------------------+-------+--------+------ ---------------+------------+---------+----------- ----+---------------------+----------------------------- ----------------------+
| | 1 | プライマリ | d | すべて | プライマリ | | | | | | | 10 | where を使用します。一時的な使用; ファイルソートの使用 |
| | 1 | プライマリ | | | 参照 | PRIMARY,emp_status | emp_status | 5 | Orangehrm_li.d.id | 48 | where | の使用
| | 1 | プライマリ | b | 参照 | emp_number,skill_id | 従業員番号 | 4 | Orangehrm_li.a.emp_number | 1 | | |
| | 1 | プライマリ | c | eq_ref | プライマリ | プライマリ | 4 | orangehrm_li.b.skill_id | 1 | where | の使用
| | 3 | 従属サブクエリ | e | すべて | | | | | | | | | 28165 | where を使用します。ファイルソートの使用 |
| | 2 | 従属サブクエリ | e | すべて | | | | | | | | | 28165 | where を使用します。ファイルソートの使用 |
+----+--------------------+-------+--------+------ ---------------+------------+---------+----------- ----+---------------------+----------------------------- ----------------------+
4

1 に答える 1

0

あなたのテーブルは、私がここで行ったように十分小さく見えます。最初に、最も内側のクエリはすべての従業員から始まり、すぐに予定テーブルに 2 つの左結合を行いました...問題の日付よりも少ない予定の MAX() を取得することで、「前の予定」を取得し、問題の日付が「次の予定」を取得した後の MIN() 予定。これで、1 人の人物について、ID と、特定の時間に基づいた前後の予定の両方を取得できます。

ここで、その結果を取得して、最初に予定表に再結合します (再度結合したままにしておきます) が、今回は同じ人物 (Terp_ID) とそれぞれの前の予定と次の予定の日付/時刻に基づいています。これが問題になるのは、1 人の人物に対してまったく同じ日付/時刻の複数のエントリがあり、複数のレコードが生成される場合のみです。

だから今、私は各人に前と次の予定の詳細を用意しています。

残りは、他のテーブルに単純に結合して、「アクティブ」の従業員ステータスと「アラビア語」基準のスキル セット (それぞれの JOIN 基準にある) のみを取得することです。それ以外の場合は、これらを WHERE 句に移動するだけです。

クエリの「日付/時刻」ベースに関しては、@variable を 1 回使用したので、予定への左結合の両方に対して使用できました。最後に、必要なそれぞれのフィールドを取得しました。これは機能する必要がありますが、データがなくても、微調整が必​​要になる場合があります。

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 に答える